sendto函数在C语言中允许的最大缓冲区长度是多少?

4
我正在使用UDP套接字实现一个简单的网络栈,希望从客户端向服务器发送约1 MB的字符串数据。然而,我不清楚在C语言中UDP的sendto() API的长度是否有限制。如果有限制并且sendto()不能处理超过限制的分组,则我必须手动将字符串分成较小的块,然后发送它们。
缓冲区的长度是否有限制?还是sendto() API会自行处理分组?
非常感谢您的帮助。

https://dev59.com/InVD5IYBdhLWcg3wTJvF - mkimball
它应该处理任何长度,但需要注意的是UDP中的每个数据包可能会出错(不到达或多次到达或包顺序混乱)。而且你无法事先知道你的数据分成了哪些数据包... - deviantfan
FYI:http://pubs.opengroup.org/onlinepubs/009695399/functions/sendto.html 表示如果消息太大,sendto会将“errno”设置为“EMSGSIZE”。因此,如果您确实需要,可以全部动态完成,并查看数据是否过大。某些情况下,我认为1MB将会太大了。 - Gábor Buella
如果您使用UDP,您必须自己处理拆分成UDP数据包的问题。但是,IP数据包的拆分和重组必须在发送方和接收方都支持您的完整数据包长度和段数。相关的RFC仅给出最小支持限制,其余取决于实际部署的硬件和软件。此外,MTU取决于网络。 - Deduplicator
1个回答

9

sendto 没有 API 限制 —— 它可以处理底层协议所能处理的任何数据量。

UDP 存在数据包限制,最大为 64K;如果超过此限制,sendto调用将会返回一个 EMSGSIZE 错误码。此外,IP 的数据包大小限制因 IPv4 和 IPv6 而异。最后,传输层有一个 MTU(最大传输单元)大小,可能是一个问题,也可能不是问题。IP 数据包可以被分成多个更小的数据包进行自动重组,除非您使用了 IP_OPTIONS setsockopt 调用来禁用分片。

应对这些复杂性的最简单方法就是让您的代码具有灵活性——检测 sendto 返回的 EMSGSIZE 错误并在出现此错误时切换到较小的消息。这种方法也很适合进行路径 MTU 发现,通常情况下可以接受较大的消息,但当您发送的消息超过路径 MTU 时,它将减小最大消息大小。

如果您只是想避免担心这些问题,发送小于或等于 1452 字节的数据包可能总是没问题的(这是 1500 字节的正常以太网负载最大值减去 40 字节的正常 IPv6 标头和 8 字节的 UDP 标头),除非您使用 VPN(在这种情况下,您需要关注封装开销)。


如果长度超过套接字发送缓冲区的大小,UDP 也会返回 EMSGSIZE。在 IPv4 中,UDP 的实际上限是 65507 字节(65535-28)。 - user207421
谢谢大家的见解!但是我不是学网络专业的,对于很多与UDP相关的事情并不是很了解。我只有一个非常基本的对UDP的理解。在运行代码和获取错误之前,我如何找出可以传递给sendto()函数的最大长度缓冲区呢? - user2058668
@user2058668:关键是你不能确定——如果网络上连接你和对话对象之间的某个地方改变了什么,数字可能会发生变化。 - Chris Dodd
有没有一种方法可以做到这一点?如果有的话,你能指导我吗? - user2058668

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接