C#异步套接字服务器接收问题

我已在此处实现了有关此post的服务器应用程序: http : //www.codeguru.com/csharp/csharp/cs_network/sockets/article.php/c8781#Client1

总结:我正在使用异步套接字ala BeginAccept(..),BeginReceive(..)。 我的服务器能够处理多个客户端,一切正常,直到客户端执行两个或多个同步发送操作,而无需等待一段时间。 客户端没有收到任何错误,因此没有得到通知,服务器没有收到第二条消息! 如果客户等待约。 第一次发送操作后100ms,一切正常。 我认为当我使用TCP时,我可以确保服务器收到消息。 (除了抛出exception)! 你能帮我解决一下吗?

这是我在服务器中实现的WaitForData(..)和OnDataReceive(..)方法

public void WaitForData(MyClient client) { try { if (pfnCallBack == null) { pfnCallBack = new AsyncCallback(OnDataReceived); } iarResult = client.Socket.BeginReceive(client.DataBuffer, 0, client.DataBuffer.Length, SocketFlags.None, pfnCallBack, client); } catch (SocketException se) { MessageBox.Show("SocketException@WaitForData" + se.Message); } } public void OnDataReceived(IAsyncResult asyn) { try { MyClient user= (MyClient)asyn.AsyncState; int iRx = user.Socket.EndReceive(asyn); byte[] receivedData = user.DataBuffer; MemoryStream memStream = new MemoryStream(); BinaryFormatter binForm = new BinaryFormatter(); memStream.Write(receivedData, 0, receivedData.Length); memStream.Seek(0, SeekOrigin.Begin); MyMessage msg = (MyMessage)binForm.Deserialize(memStream); switch (msg.Command) { case (MyMessage.MyCommand.ConnId): this.connId = (int) msg.MyObject; tsslConnStatus.Text += " | ID: " + connId.ToString(); break; case (MyMessage.MyCommand.Text): MessageBox.Show(msg.MyObject.ToString()); break; } WaitForData(server); } catch (ObjectDisposedException ode) { MessageBox.Show("ObjectDisposedException@OnReceiveData" + ode.Message); } catch (SocketException se) { MessageBox.Show("SocketException@OnReceiveData" + se.Message); } } 

CLIENT调用同步SEND METHOD TWICE或更多! 服务器INSTANCEOF MyClient

 if (server.Socket.Connected) { BinaryFormatter bf = new BinaryFormatter(); MemoryStream ms = new MemoryStream(); bf.Serialize(ms, message); MyMessage = new MyMessage(something); server.Socket.Send(ms.ToArray()); } 

所以,我认为这段代码片段必须足以让你得到我试图使用的想法! 如果您需要更多详细信息或代码片段,请告诉我我会发布它!

感谢名单!

TCP是基于流的而不是基于消息的。 One Read可以包含以下任何替代方案:

  • 消息的一个小小的weeny部分
  • 一半消息
  • 完全是一条消息
  • 一个半消息
  • 两条消息

因此,您需要使用某种方法来查看是否已到达完整的消息。 最常见的方法是:

  • 添加页脚(例如空行),表示消息结束
  • 添加包含消息长度的固定长度标头

更新

简单示例只有标题长度。

服务器端:

 var buffer = binaryFormmater.Serialize(myobj); var length = buffer.Length; networkStream.Send(length); networkStream.Send(buffer, 0, buffer.Length); 

客户端:

 var header = new buffer[4]; // TODO: You need to make sure that 4 bytes have been read. networkStream.Read(header, 0, 4); var length = BitConverter.ToInt32(buffer); var readbuffer= new byte[65535]; var bytesLeft = length; var messageStream = new MemoryStream(); while (bytesLeft > 0) { var read = networkStream.Read(readbuffer, 0, bytesLeft); messageStream.Write(readbuffer, 0, read); bytesLeft -= read, } messageStream.Seek(0, SeekOrigin.Begin); MyMessage msg = (MyMessage)binForm.Deserialize(messageStream);