C# Visual Studio

【Visual Studio 2022】C#ソケット通信アプリケーションの作成

本記事では、C#を使ってサーバーとクライアント間でメッセージをやり取りするソケット通信アプリケーションの作成方法を解説します。サーバー・クライアントの役割や通信の仕組みを理解しながら、実際に動作するアプリを作る手順をステップごとに学べます。


ソケット通信とは

ソケット通信とは、コンピュータ同士がネットワーク上でデータをやり取りするための仕組みです。
普段私たちが使うWeb通信やメール送受信、工場でつかわれるPLCとの通信など、多くのネットワーク通信の土台になっています。

ソケットの役割

ソケット(Socket)は、データの出入り口のようなものです。
プログラムはソケットを通してデータを送ったり受け取ったりします。

クライアントとサーバー

ネットワーク通信は多くの場合、以下の2つの役割で行われます。

サーバー待ち受け役。データを受け取り、必要に応じて応答する。
クライアント送信役。サーバーにデータを送り、応答を受け取る。
TCPとUDP

ソケット通信には大きく2種類あります。

TCPデータが必ず届くことを保証。信頼性重視。
UDPデータが早く届くことを重視。届かないこともある。

完成イメージ

今回作成するアプリケーションは、サーバー側とクライアント側の2つのアプリケーションで構成されます。

動作の流れは以下の通りです。
1. サーバー接続待ち
2. クライアントがサーバーに接続
3. クライアントからサーバーへ「Hello Server !」とメッセージを送信
4. サーバーがメッセージを受信
5. サーバーからクライアントへ「Hello Client !」と応答
6. クライアントがメッセージを受信

「作成するアプリケーション」


機器構成

以下の機器構成を例にアプリケーションを作成します。


サーバー側アプリケーションの作成

プロジェクト
・テンプレート:Windowsフォームアプリケーション(.NET Framework)
・言語:C#
・フレームワーク:.NET Framework 4.8
画面
コントロール
名称コントロールの種類備考
固定文字1Label
固定文字2Label
受信メッセージLabel
実行ボタンButton
コード
C#
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;

namespace ArtApp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btn_StartListen_Click(object sender, EventArgs e)
        {
            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 5000);

            //ソケットの作成
            Socket listenerSocket = new Socket(
                AddressFamily.InterNetwork,
                SocketType.Stream,
                ProtocolType.Tcp
                );

            try
            {
                //通信の受け入れ準備 (ソケットをIPとポートに結びつけ、待ち受けを開始)
                listenerSocket.Bind(localEndPoint);
                listenerSocket.Listen(10); //最大10個の接続要求をキューに保持

                //通信の確立
                //この処理はクライアントが接続するまでブロック(待機)
                using (Socket clientSocket = listenerSocket.Accept())
                {
                    //クライアントからデータを受信
                    byte[] receiveBuffer = new byte[1024];
                    int bytesReceived = clientSocket.Receive(receiveBuffer);

                    //受信データをバイト配列を文字列に変換
                    string receivedData = Encoding.UTF8.GetString(receiveBuffer, 0, bytesReceived);

                    this.lbl_ResponseData.Text = receivedData;

                    //クライアントへデータを送信
                    string responseMessage = "Hello Client !";
                    byte[] responseBytes = Encoding.UTF8.GetBytes(responseMessage);
                    clientSocket.Send(responseBytes);

                    //ソケットの機能停止をクライアントに通知
                    clientSocket.Shutdown(SocketShutdown.Both);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                if (listenerSocket != null)
                {
                    //待ち受けソケットのリソース解放
                    listenerSocket.Close();
                }
            }
        }
    }
}

クライアント側アプリケーションの作成

プロジェクト
・テンプレート:Windowsフォームアプリケーション(.NET Framework)
・言語:C#
・フレームワーク:.NET Framework 4.8
画面
コントロール
名称コントロールの種類備考
固定文字1Label
固定文字2Label
受信メッセージLabel
実行ボタンButton
コード
C#
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;

namespace ArtApp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btn_ConnectAndSend_Click(object sender, EventArgs e)
        {
            //IPエンドポイントの作成
            IPAddress serverIpAddress = IPAddress.Parse("192.168.3.20");
            IPEndPoint serverEndPoint = new IPEndPoint(serverIpAddress, 5000);

            //ソケットの作成
            Socket clientSocket = new Socket(
                AddressFamily.InterNetwork,
                SocketType.Stream,
                ProtocolType.Tcp
                );

            try
            {
                //サーバーへの接続
                clientSocket.Connect(serverEndPoint);

                //サーバーへデータを送信
                string messageToSend = "Hello Server !";
                byte[] sendBytes = Encoding.UTF8.GetBytes(messageToSend);
                clientSocket.Send(sendBytes);

                //サーバーからの応答データを受信
                byte[] receiveBuffer = new byte[1024];
                int bytesReceived = clientSocket.Receive(receiveBuffer);

                //バイトデータを文字列に変換して表示
                string responseData = Encoding.UTF8.GetString(receiveBuffer, 0, bytesReceived);

                this.lbl_ResponseData.Text = responseData;

                //ソケットの機能停止をサーバーに通知
                clientSocket.Shutdown(SocketShutdown.Both);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                if (clientSocket != null)
                {
                    //クライアントソケットのリソース解放
                    clientSocket.Close();
                }
            }
        }
    }
}

実行・動作確認

作成したアプリケーションを実行し、想定通りに動作するか確認してみましょう。

1. ノートPC1でサーバー側アプリケーションを起動します。
2. ノートPC2でクライアント側アプリケーションを起動します。
3. サーバー側アプリケーションの実行ボタン(待ち受け開始)をクリックし、待ち受け状態にします。
4. クライアント側アプリケーションの実行ボタン(接続して送信)をクリックし、「Hello Server !」を送信します。
5. サーバーからクライアントに「Hello Client !」が返ることを確認します。

完成イメージ通りに動作すれば、ソケット通信アプリケーションの作成は完了です。

今回作成したアプリケーションでは、通信処理をUIスレッド(メインスレッド)上で直接実行しているため、処理中に画面が固まったように見える場合があります。
ソケット通信では、接続待ちやデータ送受信などの待機時間が発生するため、これらを UI スレッドで処理するとアプリ全体の応答が一時的に停止してしまうためです。

実際のアプリケーション開発では、Task や Thread を用いて通信処理を別スレッドで実行する のが一般的です。
今回は、ソケット通信の基本的な流れを理解することを優先し、あえてシンプルな構成とするために UI スレッド上で動作させています。


次の記事へ

演習問題を通し、ソケット通信を使用したアプリケーションを作成します。


あなたをプロにすることを約束します。

アルチテックのインターンシップはハイレベル。

現役のシステムエンジニアがマンツーマン指導

市場価値が高い産業系システムエンジニアを目指そう!

インターンシップの募集はこちら

-C#, Visual Studio
-, , , , ,