当作用于UDP套接字时,什么可能导致sendto()发送比请求更少的字节?

时间:2014-06-04 18:56:35

标签: sockets udp sendto mtu

当作用于UDP套接字时,是什么导致sendto()发送的字节少于请求的字节数?

要求这样做的动机是找出我需要采取的预防措施,以确保我始终通过一次调用sendto()发送完整的消息,并进一步了解我需要采取步骤将消息传入单个IP数据包。我只需要确保我的信息低于某个大小,如果是这样,那么这个大小有多大?除了特定于操作系统的UDP数据报大小限制和MTU之外,是否还有其他工作(例如,I / O缓冲容量,反复无常的操作系统)?

在问过上面的原则问题后,在这篇文章的标题中,我将继续讨论一些相关的后续问题,然后在最后将问题放到上下文中。

更多问题

进一步详细说明,再次假设我们正在使用UDP套接字:

  1. 每次成功调用sendto()是否会导致发送 1 UDP数据报? (我很欣赏这可能会分成多个IP数据包)

  2. 每次成功调用recvfrom()都会准确检索 1 UDP数据报吗?

  3. 如果一封邮件将 N 次来电话发送到sendto(),那么它是否会接受recvfrom() N 次来电,即使接收机器是一个不同的平台? (我很欣赏数据报顺序无法预测)

  4. 假设我尝试发送一条大小等于或小于本地和远程系统支持的最大UDP数据报大小中较小者的消息(并且会出现一些错误,导致返回值为 -1 sendto()保证一次发送我的整个邮件?或者它可能会报告它发送的字节数少于我要求它发送的字节数?如果是这样,为什么?回到问题1。

  5. 除了问题4中的假设之外,假设我的消息不大于(MTU-UDP头-IP头)大小,是保证的结果的UDP数据报适合 1 IP数据包(至少在我的本地网络上)?

  6. 上下文

    我刚刚开始编写我的第一个基于UDP的通信协议(跨平台:例如linux,mac,windows,ios,android等)。我是套接字新手,但我知道使用像UDP这样简单的协议所带来的“成本”,并研究了以下算法/策略:

    我试图将我的所有通信分解成原子消息(即单个,自包含的UDP数据报),这些消息可能(但不一定)需要适合单个IP数据包(例如1500字节)。吞吐量和数据包丢失的实时评估将确定我是否必须缩小数据报以适应单个IP数据包(这将导致额外标头的大小损失)。其中一些将通过wifi /无线电链路,所以我希望自适应地确定“最佳”数据报大小。我知道所有接口的MTU,并且感谢在本地网络之外的数据包可能会进一步分裂,但这是我无法控制的,所以我可以忍受它。

    但是一切都取决于能够构建原子消息并且100%有信心我可以通过一次调用sendto()成功发送它,并且只需一次调用recvfrom()即可接收。我的所有应用程序级可靠性,拆分,编码和加密信息都存在于我自己的协议头中,在调用sendto()后,我无法重新拆分消息。例如。想一下消息校验和:如果整个消息不能一次性完成,则标题中的校验和不再对已发送的消息部分有效。

2 个答案:

答案 0 :(得分:1)

  

一切都取决于能够构建原子消息,并且100%有信心我可以通过一次调用sendto()成功发送它,并且只要调用一次recvfrom()就可以接收

UDP保证。数据报完整无缺地到达,或者完全没有。您所需要的只是确保套接字发送和接收缓冲区足够大,如果您遍历路由器,则每个数据报不会发送超过534个字节:这是普遍接受的限制。

答案 1 :(得分:0)

我有许多协议的经验,这些协议做出了这个确切的基本假设,即发送的任何UDP数据包将在一次呼叫中发送并在1次呼叫中接收(或根本不接收)。在应用程序级别看不到由于MTU等而发生的任何碎片。许多实时流协议限制数据包大小以限制由于碎片造成的延迟,但这一切都在封面之下。只需确保接收缓冲区足够大。