TCP通信の基本概念と実装:粘着パケット問題の解決とC#による実践例

TCPとUDP通信の特性比較

ネットワーク通信において、TCPとUDPは代表的なプロトコルです。両者の動作原理には明確な違いがあります。

TCP通信の特徴

  • 信頼性: データ転送の確実性を保証します
  • 順序性: データ到着順序が送信順と一致します
  • 接続指向: 通信前にコネクションを確立します
  • オーバーヘッド: 接続維持のためのリソース消費が発生します

UDP通信の特徴

  • 非接続型: 事前接続なしでデータ送信
  • 高速転送: ヘッダーオーバーヘッドが最小限
  • ベストエフォート: 到達保証なし

TCP粘着パケット問題の本質

TCPではデータがバイトストリームとして転送されるため、メッセージ境界が消失します。これにより、複数メッセージが単一バッファに混在する「粘着パケット」現象が発生します。

解決策:アプリケーション層プロトコルの設計

粘着パケット問題を解決するには、明確なメッセージ構造を定義する必要があります:

// プロトコル構造例
// [ヘッダー(4byte)] + [データ長(4byte)] + [ペイロード(N byte)]
public byte[] FormatMessage(int header, byte[] payload)
{
    using var ms = new MemoryStream();
    using var writer = new BinaryWriter(ms);
    writer.Write(header);
    writer.Write(payload.Length);
    writer.Write(payload);
    return ms.ToArray();
}

C#によるTCP通信ライブラリ実装

受信バッファから完全なメッセージを抽出する処理:

public Message ExtractCompleteMessage(byte[] buffer)
{
    if (buffer.Length < 8) return null;

    using var ms = new MemoryStream(buffer);
    using var reader = new BinaryReader(ms);
    
    int messageType = reader.ReadInt32();
    int payloadSize = reader.ReadInt32();
    
    if (buffer.Length - 8 >= payloadSize)
    {
        byte[] payload = reader.ReadBytes(payloadSize);
        return new Message(messageType, payload);
    }
    
    return null;
}

サーバー実装例

public void InitializeServer()
{
    var server = new TcpListenerCore();
    server.ConnectionEstablished += OnClientConnected;
    server.ConnectionTerminated += OnClientDisconnected;
    server.PacketReceived += OnDataReceived;
    server.StartListening(9100);
}

クライアント実装例

public void InitializeClient()
{
    var client = new TcpClientCore();
    client.ConnectionEstablished += OnConnected;
    client.ConnectionTerminated += OnDisconnected;
    client.PacketReceived += OnServerDataReceived;
    client.Connect("127.0.0.1", 9100);
}

拡張が必要な機能

  • マルチスレッド対応の安全性確保
  • 接続状態監視のためのハートビート機構
  • エラー処理の強化
  • 暗号化通信サポート

タグ: TCP C# ソケットプログラミング ネットワークプロトコル 粘着パケット問題

7月23日 18:15 投稿