9

C# で「SocketAsyncEventArgs」クラスを理解しようとしています。http://msdn.microsoft.com/en-us/library/system.net.sockets.socketasynceventargs.aspx

私はこのチュートリアルに従っています: http://www.codeproject.com/Articles/83102/C-SocketAsyncEventArgs-High-Performance-Socket-Cod

今、私は自分のサーバーでデータを正確に処理する方法にこだわっています。私がやろうとしているのは、接続されたクライアントに SocketAsyncEventArgs を使用し、BufferManager で 512 バイトの割り当てられた Buffer スペースを使用することです。次に、バイト [] データを、デコードおよび読み取り用のバイト [] を保持する独自のカスタム クラス (ClientPacket) にデコードします。

これで問題ありませんが、サーバーが常にデータで応答するとは限りません。質問は次のとおりです。

受信に 1 つの SocketAsyncEventArgs を使用し、ループして受信データを処理し、送信する必要があるときはいつでもプールから SocketAsyncEventArgs を割り当て、完了時にそれを返しますか?

また、読み込みが完了したことを SocketAsyncEventArgs はどのように知るのでしょうか? (新しいデータで上書きする前にbyte []バッファで終了したとき)応答しない場合、終了時にどのようにプールに返されるのですか?

4

1 に答える 1

10

すべてのニーズに対して SocketAsyncEventArgs インスタンスを 1 つだけ使用します。各リクエスト間でバッファーをリセットするだけです (新しい Byte[] に設定することにより)。

接続してソケットへの参照を取得したら、次のようにリッスンを開始します。

public void StartListening(SocketAsyncEventArgs e)
{
    ResetBuffer(e);
    e.Completed += SocketReceive;

    socket.ReceiveAsync(e);
}

バッファをリセットするヘルパー関数があります:

private void ResetBuffer(SocketAsyncEventArgs e)
{
    var buffer = new Byte[SocketBufferSize];

    e.SetBuffer(buffer, 0, SocketBufferSize);
}

次のようにデータを処理します。

private void SocketReceive(Object sender, SocketAsyncEventArgs e)
{
    ProcessData(e.Buffer, 0, e.BytesTransferred);

    ResetBuffer(e);

    socket.ReceiveAsync(e);
}

ProcessData では、必要に応じてバイト配列を使用してデータを取得できます。次のように、これを使用して MemoryStream を作成し、それをクラスに逆シリアル化します (ClientPacket と同様)。

private void ProcessData(Byte[] data, Int32 count)
{
    using (var stream = new MemoryStream(data, 0, count))
    {
        var serializer = new XmlSerializer(typeof(ClientPacket));

        var packet = serializer.Deserialize(stream);

        // Do something with the packet
    }
}

最後の質問について。フレームワークは、基礎となる TCP プロトコルなどに関するすべてを処理するため、処理するデータがあるときはいつでも呼び出されるイベント ハンドラーに依存できます。e.BytesTransferred 値を使用して、実際に受信したデータの量を示します。これは、バッファー サイズ (私のコードでは SocketBufferSize) よりも小さい場合がありますが、超えることはありません。メッセージがバッファ サイズよりも大きい場合、TCP インフラストラクチャはメッセージをバッファリングし、SocketBufferSize に基づいてチャンクで送信します (チャンクごとに 1 回イベントを発生させます)。これが問題になる場合は、メッセージの大部分が 1 つのチャンクで受信されるまで、SocketBufferSize を増やしてください。

チャンキングの欠点は、メッセージがインフラストラクチャによってマージされる可能性があることです。つまり、最初のメッセージがいつ終了したかを知る方法が必要になる場合があります。典型的なアプローチには、メッセージの長さを示す 4 バイトの整数をメッセージの前に付けることが含まれます。必要に応じて、さらに詳しく説明できます。

それが役立つことを願っています。

于 2012-01-26T13:31:52.360 に答える