我目前正在C#中编写一些异步UDP网络代码。我来回发送小数据包(目前为止每个数据少于50个字节),我的第一个想法是将它们分成两个不同的数据包,仍然将其作为一个数据包发送,但是将其作为两个接收。因此,总是将标头或额外信息包添加到真实包的开头。那将包含ID和数据长度。
所以我认为我可以在接收端(异步接收)拆分它,然后首先接收标头然后接收实际信息。这样我就不用担心数据包和“数据包标题”之间的顺序了。
所以我编写的代码基本上是这样的: 客户端将30个字节的数据发送到服务器,其中前3个字节是数据包头。
服务器将调用(PACKET_HEADER_SIZE = 3):
socket.BeginReceiveFrom(state.Buffer, 0, PACKET_HEADER_SIZE, SocketFlags.None, ref endPoint, ReceivePacketInfo, state);
然后收到数据:
private void ReceivePacketInfo(IAsyncResult ar)
{
StateObj state = (StateObj) ar.AsyncState;
int bytesRead = socket.EndReceiveFrom(ar, ref endPoint);
state.BytesReceived += read;
if (state.BytesReceived < state.Buffer.Length)
{
_socket.BeginReceiveFrom(state.Buffer, state.BytesReceived, state.Buffer.Length - state.BytesReceived, SocketFlags.None, ref endPoint, ReceivePacketInfo, state);
}
else
{
//my thought was to receive the rest of the packet here
}
}
但是在调用socket.EndReceiveFrom(ar)时我得到一个SocketException:
“在数据报套接字上发送的消息大于内部消息缓冲区或其他一些网络限制,或者用于接收数据报的缓冲区小于数据报本身”
所以现在我有几个问题。
在调用EndReceiveFrom之前,我是否必须确保收到整个数据包(在这种情况下是标头和数据包)?
我可以假设我要么一次性获取整个数据包,也不会得到任何结果,以便我的ReceivePacketInfo中的if语句是冗余的(当然,只要它的大小小于最大数据包大小)? / p>
如果我不能,是否有解决问题的好方法?我可以标记我的所有数据包标头和我的所有数据包,以便能够将它们映射到一起。我还可以尝试使用标准化的“数据包结束”,这样我就可以阅读,直到我到达数据包的末尾。
提前感谢您的帮助!
答案 0 :(得分:2)
我可以假设我会一次性获得整个数据包或者什么也得不到
这几乎是UDP可以保证的唯一内容 - 数据包的内容。如果收到数据包,则保证具有相同的大小和相同的内容。所以你必须确保你的缓冲区对于数据包足够大。
无法保证数据包的顺序和传送本身。由您和您的应用程序来处理丢弃的数据包和无序数据包。