2012-03-06 24 views
1

私はC#でソケットプログラミングを扱っています。私は、指定されたプロトコルでサーバと通信しているクライアントアプリケーションを構築する必要があります。非同期ソケットクライアントを受信

非同期送信メソッドを正常に実装しましたが、受信アルゴリズムの実装に問題があります。同期受信メソッドは正常に動作しています。

まず、着信メッセージを連続して読み取ってACKする必要があります。正しいように、受信したすべてのメッセージにはターミネータ(0x0c)が付いている必要があります

3つのスレッドでMessageFlowという名前のマルチスレッドクラスを構築しました。メッセージの送信を処理し、もう1つはメッセージの受信を処理し、受信したメッセージを解釈して何かをする。

受信スレッドのワーカー関数がこの

private void ReadSocketWorker() 
{ 
    while (this.canRun) 
    { 
    xComClient.Receive(); 
    xComClient.receiveDone.WaitOne(); 
    Thread.Sleep(10); 
    } 
} 

XComClientのように見えるが、私のクラスには、メッセージを送受信するためのソケットとすべてのメソッドを持っています。

public void Receive() 
{ 
    try 
    { 
     StateObject state = new StateObject(); 
     state.workSocket = socketClient; 
     socketClient.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state); 
    } 
    catch (Exception e) 
    { 
     throw e; 
    } 
} 

private void ReceiveCallback(IAsyncResult ar) 
     { 
      try 
      { 
       StateObject state = (StateObject)ar.AsyncState; 
       Socket client = state.workSocket; 

       // Read data from the remote device. 
       int iReadBytes = client.EndReceive(ar); 

       if (iReadBytes > state.GetBufferSize()) 
       { 
        byte[] bytesReceived = new byte[iReadBytes]; 
        Buffer.BlockCopy(state.buffer, 0, bytesReceived, 0, iReadBytes); 
        state.responseList.Enqueue(bytesReceived); 
        client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, 
         new AsyncCallback(ReceiveCallback), state); 
       } 
       else 
       { 
        byte[] bytesReceived = new byte[iReadBytes]; 
        Buffer.BlockCopy(state.buffer, 0, bytesReceived, 0, iReadBytes); 
        state.responseList.Enqueue(bytesReceived); 
        BuildReceivedMessage(state); 
        receiveDone.Set(); 
       } 
      } 
      catch (Exception e) 
      { 
       throw e; 
      } 
     } 

public class StateObject 
{ 
    public Socket workSocket = null; 
    public const int BufferSize = 20480; 
    public byte[] buffer = new byte[BufferSize]; 

    public Queue<byte[]> responseList = new Queue<byte[]>(); 

    public int GetBufferSize() 
    { 
     return BufferSize; 
    } 
} 

私は間違っていますか?

答えて

1

デザインは、同期プログラミングと非同期プログラミングのハイブリッドです。適切に設計された非同期クラスはスレッドをまったく使用する必要はありませんが、.NETでスレッドを管理できるようにします。

私は実際にthrow e;が例であることを願っています。それはスタックトレースを破壊しているので(したがって例外が発生した場所を隠している) Aは、この方法は次のように見ることができ受けるあなたは私の記事Don't catch that exceptionを読むことができますし、私の他の記事は

exceptionsをタグ付け:

void OnReceive(IAsyncResult ar) 
{ 
    AppendInternalReadBuffer(); 
    CheckInternalReadBufferForMessageAndProcessIt(); 
    ReadAgain(); 
} 
クライアントごとに一度に複数のメッセージをproccessingからサーバーをブロックします

。あなたがそれをしたくない場合(事を複雑にする)、をCheckInternalReadBufferForMessageAndProcessItに使うことができます。

+0

ありがとうございました。同期/非同期のアプローチを組み合わせることで、私はまったく混乱していた – Francesco

2

他に何もしていないスレッドで非同期I/Oを使用することには、本当に意味がありません。私はこの意思決定を再考するだろう。

関連する問題