我有一个简单的TCP服务器,通过GPRS与一些设备通信 . 它长时间正常工作没有任何问题 . 现在,设备(客户端设备,发送数据)发生了变化,并且它们发送的数据比以前多得多,TCP消息大小可能比之前大10倍 . 早先它是最大1024字节/数据消息,现在它可以超过1万字节/消息 .
正如我所看到的 - 正如TCP所预测的那样 - 有许多消息被“破坏”,所以不是完整的消息,只有一部分到达,后来可以到另一部分等 .
我认为我的服务器 - 基于异步模式 - 以错误的方式处理这种情况,我认为该错误在我的RecieveCallBack函数中 . 我找不到正确处理这种情况的方法 . 我怎样才能做到这一点?
这是我的RecieveCallBack功能:
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
谢谢
UPDATE: 客户端已连接,因为它们可以连接,因此由GSM网络决定 . 他们甚至可以连接几天,他们每分钟都会发送数据 . 客户端设备的协议不同,存在具有不同种类协议的不同类型的设备 . 其中一个在消息的末尾有分隔符和CRC,其他没有 .
3 回答
这不是TCP中的数据包 . 它是一种面向流的协议 . 这意味着当您阅读套接字时,您可以获得比预期更少的数据 . 您需要检查读取大小,如果您有一个简短的读取,则再次读取其余数据 .
对于C中的示例:
你需要message framing . 协议必须指定消息的大小 - 通常是常量已知大小,长度前缀或使用消息分隔符 .
我不确定应用程序的其余部分是如何看的,但我认为问题出在以下几行: -
如果数据包被分段,即对于同一连接多次调用接收回调,则state.Buffer将被最后接收的数据包覆盖,这是在state.Buffer中将数据复制到偏移量0时 .
根据您的需求,您可能需要在StateObject中使用更多状态:)因此您可以附加数据而不是覆盖 .
希望这个暗示有所帮助 .