关于UDP / IP和sendto / recvfrom返回值的混淆

时间:2009-04-23 02:03:15

标签: c++ networking udp

我第一次使用C ++中的UDP套接字,我不确定我是否理解它们是如何工作的。我知道sendto / recvfromsend / recv通常会返回实际发送或接收的字节数。我听说这个值可以任意小(但至少为1),并且取决于套接字缓冲区中的数据量(读取时)或缓冲区中剩余的可用空间量(写入时)。

如果sendtorecvfrom仅保证一次发送或接收1个字节,并且数据报可以无序接收,那么任何UDP协议如何保持连贯?这是否意味着当我收到消息中的字节时可以任意洗牌?有没有办法保证一次发送或接收消息?

4 个答案:

答案 0 :(得分:3)

比那更强大。 UDP确实提供了完整的包;缓冲区大小可以任意小,但必须包括数据包中发送的所有数据。但是还有一个大小限制:如果你想发送大量数据,你必须将其分解成数据包,并能够自己重新组装它们。它也没有保证交付,所以你必须检查以确保一切都通过。

但是,由于您可以使用UDP实现所有TCP,因此必须可以实现。

通常,您使用UDP做的是制作离散的小数据包。

隐喻地认为UDP就像发送明信片和TCP一样打电话。当您发送明信片时,您无法保证交付,因此您需要做一些回复确认的事情。通过电话,您知道存在连接,并立即听到答案。

答案 1 :(得分:1)

没有。使用sendto,您可以发送数据包,这些数据包可以包含一个字节。 如果您将10个字节作为单个sendto调用发送,则这10个字节将被发送到单个数据包中,这将按照您的预期一致地接收。

当然,如果您决定逐个发送这10个字节,每个字节都有一个sendto调用,那么您确实发送和接收10个不同的数据包(每个包含1个字节),它们可以按任意顺序排列

这类似于通过邮政服务发送书籍。您可以将书籍整体打包成一个单独的框,或者拆掉每一页并将每个页面作为单独的字母发送。在第一种情况下,包装体积较大,但您将本书作为单个有序实体接收。在后者中,每个包都很轻,但祝你好运;)

答案 2 :(得分:1)

实际上你可以发送一个长度为0字节的UDP数据报。发送的所有内容都是IP和UDP标头。另一方面的UDP recvfrom()将返回长度为0.与TCP不同,这并不意味着对等方关闭了连接,因为UDP没有“连接”。

答案 3 :(得分:1)

我有一个客户端程序,它在专用于等待UDP套接字上的传入数据的线程中使用阻塞选择(NULL超时参数)。即使它是阻塞的,选择有时也会返回,并指示单个读取描述符是“就绪”。随后的recvfrom返回0。

经过一些实验,我发现至少在Windows上,向主机上的端口发送 UDP数据包,而不期望它会导致后续的recvfrom获得0字节。我怀疑某种拒绝通知可能来自另一端。我现在用它作为提醒,我忘记在服务器上启动查找客户端传入流量的过程。

顺便说一句,如果我改为“发送”一个有效但未使用的IP地址,那么select不会返回就绪状态并按预期阻塞。我还发现阻塞与非阻塞套接字没有区别。