C#でTCPのソケット接続を待ち受けるサーバー機能を実装する方法

2024年8月10日土曜日

C#

t f B! P L

はじめに

TCP(Transmission Control Protocol)は、ネットワーク通信において信頼性の高いデータ転送を提供するプロトコルです。サーバーはクライアントからの接続を受け付け、通信を行うことができます。本記事では、C#で簡単なTCPサーバーを作成し、その機能についてわかりやすく解説します。

TCPサーバーの基本的な仕組み

TCPサーバーは、特定のIPアドレスとポートでクライアントからの接続を待機します。クライアントが接続してくると、サーバーはその接続を受け入れ、クライアントとデータのやり取りを行います。通信が終了すると、接続を閉じます。

C#では、TcpListenerクラスを使用してTCPサーバーを簡単に実装できます。

TCPサーバーのコード例

以下は、C#でTCPサーバーを実装するための基本的なコード例です。

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

class TcpServer
{
    private static TcpListener listener;
    private static bool isRunning = true;

    public static void Main()
    {
        // サーバーのIPアドレスとポート番号を設定
        IPAddress ipAddress = IPAddress.Any; // 任意のネットワークインターフェースで接続を受け入れる
        int port = 5000;

        listener = new TcpListener(ipAddress, port);

        // リスナーを開始
        listener.Start();
        Console.WriteLine($"Server started on {ipAddress}:{port}");

        // クライアントの接続を待機するスレッドを開始
        Thread clientThread = new Thread(new ThreadStart(ListenForClients));
        clientThread.Start();

        // サーバーを終了するためにEnterキーを押すまで待機
        Console.WriteLine("Press Enter to stop the server...");
        Console.ReadLine();
        isRunning = false;

        // リスナーを停止
        listener.Stop();
        Console.WriteLine("Server stopped.");
    }

    private static void ListenForClients()
    {
        while (isRunning)
        {
            try
            {
                // クライアントからの接続を待機
                TcpClient client = listener.AcceptTcpClient();
                Console.WriteLine("Client connected.");

                // クライアントごとに別のスレッドで処理
                Thread clientHandlerThread = new Thread(() => HandleClientComm(client));
                clientHandlerThread.Start();
            }
            catch (SocketException ex)
            {
                // サーバーが停止された場合、AcceptTcpClientは例外をスローする
                if (isRunning)
                {
                    Console.WriteLine("SocketException: " + ex.Message);
                }
            }
        }
    }

    private static void HandleClientComm(TcpClient client)
    {
        // ネットワークストリームを取得
        NetworkStream stream = client.GetStream();

        // バッファサイズを設定
        byte[] buffer = new byte[1024];
        int bytesRead;

        try
        {
            // クライアントからのデータを読み取る
            while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0)
            {
                // 受信したデータを文字列に変換
                string message = Encoding.ASCII.GetString(buffer, 0, bytesRead);
                Console.WriteLine("Received: " + message);

                // クライアントにデータを送信(エコーバック)
                byte[] response = Encoding.ASCII.GetBytes("Echo: " + message);
                stream.Write(response, 0, response.Length);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception: " + ex.Message);
        }
        finally
        {
            // 接続を閉じる
            client.Close();
            Console.WriteLine("Client disconnected.");
        }
    }
}

コードの解説

サーバーの起動と接続待機

最初に、TcpListenerを使用して特定のIPアドレスとポートでサーバーを起動します。IPAddress.Anyは、任意のネットワークインターフェースで接続を受け入れる設定です。サーバーは、listener.Start()によって開始されます。

listener = new TcpListener(ipAddress, port);
listener.Start();
Console.WriteLine($"Server started on {ipAddress}:{port}");

クライアントの接続処理

サーバーは、クライアントの接続をlistener.AcceptTcpClient()で待機します。接続が受け入れられると、TcpClientオブジェクトが返されます。その後、各クライアントごとに別のスレッドで通信を処理します。

TcpClient client = listener.AcceptTcpClient();
Console.WriteLine("Client connected.");
Thread clientHandlerThread = new Thread(() => HandleClientComm(client));
clientHandlerThread.Start();

クライアントとの通信

クライアントとの通信は、NetworkStreamを通じて行われます。stream.Read()でクライアントからのデータを読み取り、stream.Write()でクライアントにデータを送り返します。この例では、受信したメッセージをそのまま送り返すエコーバック機能を実装しています。

int bytesRead;
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0)
{
    string message = Encoding.ASCII.GetString(buffer, 0, bytesRead);
    Console.WriteLine("Received: " + message);

    byte[] response = Encoding.ASCII.GetBytes("Echo: " + message);
    stream.Write(response, 0, response.Length);
}

サーバーの停止

サーバーを停止するには、listener.Stop()を呼び出します。このコードでは、Enterキーが押されるまでサーバーが動作し続けるようにしています。

Console.WriteLine("Press Enter to stop the server...");
Console.ReadLine();
isRunning = false;
listener.Stop();
Console.WriteLine("Server stopped.");

まとめ

今回の記事では、C#でTCPサーバーを実装する方法を紹介しました。このサンプルコードは、クライアントとの基本的な通信を行うための基盤を提供します。さらに複雑な処理を追加することで、ファイル転送やデータベースへの保存など、さまざまなネットワークアプリケーションを構築することができます。TCP通信の基礎を理解し、応用することで、ネットワークプログラミングのスキルを高めていきましょう。

スポンサーリンク
スポンサーリンク

このブログを検索

Profile

自分の写真
Webアプリエンジニア。 日々新しい技術を追い求めてブログでアウトプットしています。
プロフィール画像は、猫村ゆゆこ様に書いてもらいました。

仕事募集もしていたり、していなかったり。

QooQ