美好的一天,
我正在使用VC ++开发一个应用程序,它在Windows XP上使用UDP协议和winsock进行通信。以前我已经能够假设该工具接收的所有数据包都来自单个目标。但是我现在正在接收广播。监听线程的开销很小,应该将所有时间都花在下面一行:
rv = recvfrom(socket,
p_buffer_p,
p_size,
0,
(sockaddr*)&clientService_in, //This is set to do a broadcast recv
&SenderAddrSize);
我的问题是我是否可以假设我从recvfrom返回的缓冲区来自单个目标。也就是说,发送应用程序中的1个调用发送应用程序等于从接收应用程序中的recvfrom返回1?或者多个发件人的多个发送可以合并为1?
我假设来自目标的单个发送不能从recvfrom分成多个返回。我一直都是这样,从来没有遇到任何问题。
还有一件事,它是一个SOCK_DGRAM类型的套接字。
答案 0 :(得分:6)
不,无法拆分UDP消息。他们在被送出时到达。此外,不会连接多个UDP消息。
因此,N发送消息对应于N个recvfrom呼叫。
引自wiki:
数据报 - 单独发送数据包并进行检查 诚信只有在他们到达时。数据包有明确的界限 在收到时很荣幸,这意味着在接收器上进行读取操作 socket将生成最初发送的完整消息。
答案 1 :(得分:2)
你是正确的,一次调用recvfrom()将返回最多一个UDP数据报。 但不能保证每个数据报都会实际到达。
特别是,如果您发送的UDP数据报太大,它可能会在网络级别(碎片)被分割成碎片,这会增加数据报被丢弃的可能性(因为丢失任何碎片会导致丢失)整个)。您没有在应用程序级别看到碎片,因为网络级别会为您重新组装数据包。
事情变得非常棘手,因为不可能提前知道究竟有多大。有各种各样的算法可供查找,但它们都相当于试验和错误。更糟糕的是,防火墙,路由器和操作系统可以(并且通常会)随着时间的推移改变其对碎片数据报的行为。可能存在这样的情况:特定大小或组合的数据包将始终被丢弃,因为它违反了某些防火墙规则。
所以永远不要假设sendto()必然会产生recvfrom(),并尝试保持数据报的小(小于1400字节是相当安全的,小于512字节是非常安全的)。