2010-12-30 6 views
1

私はサーバとクライアントとの簡単なtcp/ipチャットプログラムを持っています。最初にパケットを送信すると、クライアントに送信されますが、NetworkStream.Readの実行中は実行が停止され、例外はスローされません。私が送る次のパケットは完全に読み込まれ、処理されます。私が気付いた別の奇妙なことは、サーバーから情報を取得してもデバッグシンボルを置いてスキップする必要がある場合でも、MyNetworkStream.DataAvailableは常にfalseであることです。私はすべてのコードを投稿することができればいいと思っていますが、それは長いので、私はネットワークストリームに読み書きする場所に投稿します。NetworkStream.Readが最初に動作しません

public void Listen(int byteLength) 
     { 
      var buffer = new byte[byteLength]; 
      MySocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(Read), buffer); 
     } 

     private void Read(IAsyncResult ar) 
     { 
      while (MySocket.Connected) 
      { 
      MyNetworkStream = new NetworkStream(MySocket); 
      var buffer = new byte[((byte[])ar.AsyncState).Length]; 
      if (!MyNetworkStream.DataAvailable) 
       throw new Exception("Data not available"); 
       MyNetworkStream.Read(buffer, 0, buffer.Length); <------Here it stops execution without throwing an exception 
       string content = Encoding.ASCII.GetString(buffer); 
       if(OnRead == null) 
        continue; 
       var e = new CommandEventArgs(null, content); 
       Control target = null; 
       if (OnRead.Target is Control) 
        target = (Control)OnRead.Target; 
       if (target != null && target.InvokeRequired) 
        target.Invoke(OnRead, this, e); 
       else 
        OnRead(this,e); 

      } 
     } 


     public void Write(string message) 
     { 
      try 
      { 
       var buffer = Encoding.ASCII.GetBytes(message); 
       MySocket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, null, null); 
       if (OnWrite != null) 
       { 
        var target = (Control)OnWrite.Target; 
        if (target != null && target.InvokeRequired) 
        { 
         target.Invoke(OnWrite, this, new EventArgs()); 
        } 
        else 
        { 
         OnWrite(this, new EventArgs()); 
        } 
       } 
      } 
      catch 
      { 

      } 
     } 
+1

TCPの重要な点の1つは、パケットとしてではなくストリームとしてデータを配信することです。 1回の書き込み呼び出しが到着し、複数の書き込み呼び出しが一緒に到着することがあります。 – CodesInChaos

答えて

2

BeginReceiveを非同期にメッセージを待って、あなたのバッファを満たします。その後、ソケットから同期的に読み取りを開始し、プロセス内の最初のメッセージを上書きします。

読み込んだバイト数を返すEndReceiveを呼び出してから、さらに多くのバイトを読み取ろうとする前にバッファを処理する必要があります。

1

問題に直接関係しているかどうかはわかりませんが、Readメソッドを間違って使用しています。あなたはデータをバッファに読み込んでいますが、実際に読み込まれたデータの量は無視されています。つまり、Readの呼び出しは常に要求されたデータを返すため、完全に埋め込まれていないバッファ全体をデコードします。あなたが実際のデータで満たされているどのくらいのバッファの知っているように、

Read呼び出しの戻り値を取得します。

int len = MyNetworkStream.Read(buffer, 0, buffer.Length); 
string content = Encoding.ASCII.GetString(buffer, 0, len); 
0

ストリームから完全なデータを取得するには、EndRecieveを実装する必要があります。

public static void Read_Callback(IAsyncResult ar){ 
    StateObject so = (StateObject) ar.AsyncState; 
    Socket s = so.workSocket; 

int read = s.EndReceive(ar); 

if (read > 0) { 
     so.sb.Append(Encoding.ASCII.GetString(so.buffer, 0, read)); 
     s.BeginReceive(so.buffer, 0, StateObject.BUFFER_SIZE, 0, 
           new AsyncCallback(Async_Send_Receive.Read_Callback), so); 
} 
else{ 
    if (so.sb.Length > 1) { 
      //All of the data has been read, so displays it to the console 
      string strContent; 
      strContent = so.sb.ToString(); 
      Console.WriteLine(String.Format("Read {0} byte from socket" + 
          "data = {1} ", strContent.Length, strContent)); 
    } 
    s.Close(); 
} 
} 
+0

私は決して 'else'に行くことはできません。 s.BeginReceiveに到達すると、すべてのデータがすでに処理されている場合、別のメッセージが送信されるまでRead_Callbackは呼び出されません。送信されたパケットごとにすべてのデータがどのように読み取られたかを知る方法はありますか? – Eitan

関連する問題