TCP消息损坏

我有一个简单的TCP服务器,通过GPRS与一些设备通信。 它长时间正常工作没有任何问题。 现在,设备(客户端设备,发送数据)发生了变化,并且它们发送的数据比以前多得多,TCP消息大小可能比之前大10倍。 早先它是最大1024字节/数据消息,现在它可以超过1万字节/消息。

正如我所看到的 – 正如TCP所预测的那样 – 有许多消息被“破坏”,所以不是完整的消息,只有一部分到达,后来可以到另一部分等。

我认为我的服务器 – 基于异步模式 – 以错误的方式处理这种情况,我认为该错误在我的RecieveCallBack函数中。 我找不到正确处理这种情况的方法。 我怎样才能做到这一点?

这是我的RecieveCallBackfunction:

public void RecieveCallBack(IAsyncResult ar) { StateObject state = (StateObject)ar.AsyncState; try { Socket handler = state.WorkSocket; int read = handler.EndReceive(ar); if (read > 0) { var data = new byte[read]; Array.Copy(state.Buffer, 0, data, 0, read); } else { if ((handler.Connected == false) || (handler.Available == 0)) { Close(state); return; } } } catch (System.Net.Sockets.SocketException) { Close(state); } catch (System.Exception exc) { Debug.Assert(false, exc.Message); HandleSocketError(state, exc); } } 

.NET4 / C#/ VS2010

谢谢

更新:客户端可以连接,因此它可以连接到GSM网络。 他们甚至可以连接几天,他们每分钟都会发送数据。 客户端设备的协议不同,存在具有不同种类协议的不同类型的设备。 其中一个在消息的末尾有分隔符和CRC,其他没有。

你需要消息框架 。 协议必须指定消息的大小 – 通常是常量已知大小,长度前缀或使用消息分隔符。

这不是TCP中的数据包。 它是一种面向流的协议。 这意味着当您阅读套接字时,您可以获得比预期更少的数据。 您需要检查读取大小,如果您有一个简短的读取,则再次读取其余数据。

对于C中的示例:

 int read_data(int sock, int size, unsigned char *buf) { int bytes_read = 0, len = 0; while (bytes_read < size && ((len = recv(sock, buf + bytes_read,size-bytes_read, 0)) > 0)) { bytes_read += len; } if (len == 0 || len < 0) doerror(); return bytes_read; } 

我不确定应用程序的其余部分是如何看的,但我认为问题出在以下几行: –

 Array.Copy(state.Buffer, 0, data, 0, read); 

如果数据包被分段,即对于同一连接多次调用接收回调,则state.Buffer将被最后接收的数据包覆盖,这是在state.Buffer中将数据复制到偏移量0时。

根据您的需求,您可能需要在StateObject中使用更多状态:)因此您可以附加数据而不是覆盖。

希望这个暗示有所帮助。