日安,
我正在用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的单个返回中获得的缓冲区来自单个目标。也就是说,在发送应用中调用一次send是否等于接收应用中的recvfrom返回1?或者,来自多个发送者的多个发送可以合并为1个吗?
我假设来自目标的单个发送不能被拆分成来自recvfrom的多个返回。我一直在假设这一点,而且从来没有遇到过问题。
还有一件事,它是一种SOCK_DGRAM类型的套接字。
发布于 2012-01-06 03:56:45
不能,UDP报文不能拆分。他们是按原样到达的。此外,多个UDP消息不会连接在一起。
因此,N个sendto消息对应于N个recvfrom呼叫。
引用自wiki
数据报-数据包单独发送,只有到达时才会检查其完整性。数据包具有明确的边界,在接收时会遵守这些边界,这意味着在接收方套接字的读取操作将生成原始发送的完整消息。
发布于 2012-01-10 06:38:12
对recvfrom()的单个调用最多只能返回一个UDP数据报,这一点是正确的。但不能保证每个数据报都会真正到达。
特别是,如果您发送的UDP数据报太大,它可能会在网络级别被分割成碎片(碎片),这会增加数据报被丢弃的可能性(因为任何碎片的丢失都会导致整个数据报的丢失)。您看不到应用程序级别的碎片,因为网络级别会为您重新组装数据包。
事情可能会变得非常棘手,因为事先不可能确切地知道多大才是太大。有各种算法可以找到答案,但它们都是试错。更糟糕的是,随着时间的推移,防火墙、路由器和操作系统可以(而且经常确实)改变它们对零碎数据报的行为。可能会出现这样的情况:特定大小或组成的数据包总是会被丢弃,因为它违反了某些防火墙规则。
因此,永远不要假设sendto()必然会导致recvfrom(),并尽量保持数据报小(小于1400字节是相当安全的,小于512字节是非常安全的)。
https://stackoverflow.com/questions/8748711
复制相似问题