当作用于UDP套接字时,是什么导致sendto()
发送的字节少于请求的字节数?
要求这样做的动机是找出我需要采取的预防措施,以确保我始终通过一次调用sendto()
发送完整的消息,并进一步了解我需要采取步骤将消息传入单个IP数据包。我只需要确保我的信息低于某个大小,如果是这样,那么这个大小有多大?除了特定于操作系统的UDP数据报大小限制和MTU之外,是否还有其他工作(例如,I / O缓冲容量,反复无常的操作系统)?
在问过上面的原则问题后,在这篇文章的标题中,我将继续讨论一些相关的后续问题,然后在最后将问题放到上下文中。
更多问题
进一步详细说明,再次假设我们正在使用UDP套接字:
每次成功调用sendto()
是否会导致发送 1 UDP数据报? (我很欣赏这可能会分成多个IP数据包)
每次成功调用recvfrom()
都会准确检索 1 UDP数据报吗?
如果一封邮件将 N 次来电话发送到sendto()
,那么它是否会接受recvfrom()
的 N 次来电,即使接收机器是一个不同的平台? (我很欣赏数据报顺序无法预测)
假设我尝试发送一条大小等于或小于本地和远程系统支持的最大UDP数据报大小中较小者的消息(并且会出现一些错误,导致返回值为 -1 )sendto()
保证一次发送我的整个邮件?或者它可能会报告它发送的字节数少于我要求它发送的字节数?如果是这样,为什么?回到问题1。
除了问题4中的假设之外,假设我的消息不大于(MTU-UDP头-IP头)大小,是保证的结果的UDP数据报适合 1 IP数据包(至少在我的本地网络上)?
上下文
我刚刚开始编写我的第一个基于UDP的通信协议(跨平台:例如linux,mac,windows,ios,android等)。我是套接字新手,但我知道使用像UDP这样简单的协议所带来的“成本”,并研究了以下算法/策略:
但是一切都取决于能够构建原子消息并且100%有信心我可以通过一次调用sendto()
成功发送它,并且只需一次调用recvfrom()
即可接收。我的所有应用程序级可靠性,拆分,编码和加密信息都存在于我自己的协议头中,在调用sendto()
后,我无法重新拆分消息。例如。想一下消息校验和:如果整个消息不能一次性完成,则标题中的校验和不再对已发送的消息部分有效。
答案 0 :(得分:1)
一切都取决于能够构建原子消息,并且100%有信心我可以通过一次调用sendto()成功发送它,并且只要调用一次recvfrom()就可以接收
UDP保证。数据报完整无缺地到达,或者完全没有。您所需要的只是确保套接字发送和接收缓冲区足够大,如果您遍历路由器,则每个数据报不会发送超过534个字节:这是普遍接受的限制。
答案 1 :(得分:0)
我有许多协议的经验,这些协议做出了这个确切的基本假设,即发送的任何UDP数据包将在一次呼叫中发送并在1次呼叫中接收(或根本不接收)。在应用程序级别看不到由于MTU等而发生的任何碎片。许多实时流协议限制数据包大小以限制由于碎片造成的延迟,但这一切都在封面之下。只需确保接收缓冲区足够大。