2012-01-05 34 views
3

美好的一天,UDP recv/recvfrom多个发件人

我正在开发一个在VC++中使用UDP协议与Windows XP上的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?

我假设来自目标的单个发送无法从recvfrom分裂为多个返回。无论如何,我一直认为这个问题并没有问题。

还有一件事,它是一个SOCK_DGRAM类型的套接字。

回答

6

不,不能拆分UDP消息。他们是在他们被派往时到达的。另外,多个UDP消息不会连接在一起。

因此,N个sendto消息对应于N个recvfrom调用。从wiki

报价:

数据报 - 数据包单独发送,并检查,只有当他们到达 完整性。数据包具有明确的界限,在接收到数据包之后 将被兑现,这意味着在接收器处的读取操作将会产生完整的消息,如其最初发送的那样。

+0

好的,谢谢。我读过其他地方发布的一些东西,似乎表明它们可能会分裂并变得松软,但我想这是针对不同的协议。我不熟悉winsock中连接之间的差异。 – Ian 2012-01-05 20:08:13

+0

@Ian该协议可能是基于流的协议(TCP/SCTP) – INS 2012-01-05 20:10:53

2

你是正确的,一个单一的通话给recvfrom()将最多一个UDP数据包返回。 但是不能保证每个数据报都会真正到达。

特别是,如果您发送的UDP数据报过大,它可能会在网络级别分裂成碎片(碎片),从而增加数据报被丢弃的可能性(因为任何碎片的丢失都会导致整体损失)。您在应用程序级别看不到碎片,因为网络级别会为您重新组装数据包。

事情会变得非常棘手,因为事先不可能知道究竟有多大,有各种算法可供查找,但它们都属于试验和错误。更糟的是,防火墙,路由器和操作系统可以(并且经常)随着时间的推移改变其对碎片数据报的行为。可能会出现这样的情况,即特定大小或组合的数据包总是会被丢弃,因为它违反了某些防火墙规则。因此,不要假设sendto()必然会导致recvfrom(),并尝试保持数据报的小(小于1400字节相当安全,小于512字节非常安全)。