2012-01-26 31 views
7

C#で 'SocketAsyncEventArgs'クラスを理解しようとしています。 http://msdn.microsoft.com/en-us/library/system.net.sockets.socketasynceventargs.aspxC#SocketAsyncEventArgsがデータの送受信を処理する

私はこのチュートリアルを次のです:http://www.codeproject.com/Articles/83102/C-SocketAsyncEventArgs-High-Performance-Socket-Cod

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

これはすべてが順調であるが、常にデータとの質問に応答しない私のサーバーは、次のとおりです。

は、私の周り、プールたびからSocketAsyncEventArgsを割り当て、データを受信処理する受信し、ループの1つのSocketAsyncEventArgsを使用しています私はそれを完了して返す必要がありますか?

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

答えて

8

私はすべてのニーズに合わせて1つのSocketAsyncEventArgsインスタンスのみを使用します。私は各リクエスト間でバッファをリセットするだけです(新しい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); 
} 

を私はデータを処理like:

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

    ResetBuffer(e); 

    socket.ReceiveAsync(e); 
} 

ProcessDataでは、必要に応じてバイト配列を使用してデータを取り込むことができます。あなたの最後の質問については

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 
    } 
} 

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

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

希望に役立ちます。

+0

あなたはそれを新しいbyte []に​​設定すると言っていますが、すべてのSocketAsyncEventArgsに大きなバッファブロックを共有しています。そのバッファブロックをパケットで読み取ると、バッファブロックは次の着信によって上書きされますdata、たとえbyte []配列をコピーしても、Buffer Blockを使ってデータを送受信することはできませんか?また、受信操作がいつでも発生する可能性がある場合、同じオブジェクトでデータを送信するにはどうすればよいですか? –

+1

あなたは2台のマシン間で1つのソケット接続を想定しているようです。多くの同時接続を処理するときは、SocketAsyncEventArgsを1つだけ再利用することはできません。 (これはSocketAsyncEventArgsのために構築されたものです)。 –

+0

SonOfPirateに感謝します。大量のデータを受け取ったらもっと詳しく説明できます。終わりに達する前にReceiveAsyncを再呼び出しする必要がある場合は特に明記してください。またはフレームワークは私のためにそれを行いますか? –

関連する問題