linux 应用层用udp发送数据时有大小限制吗?

我想如果应用层发送的数据过大,到了udp层不得不分片,比如说分成了3个包,接收的一方可能收不全这三个包,或者这三个包乱序了,而且这种乱序由于应用层数据被迫在udp层分片,也就意味着无法通过在应用层数据前添加信息头解决,这是否意味着应用层使用udp发送数据最好不要超过一定的大小?

从理论上来说,UDP数据的总长度为 65535(IP最大长度)-20(IP头)-8(UDP头) = 65507个字节,但大多数系统都达不到这个长度。这一般是受到两个方面的因素限制:
1) 应用程序编程接口限制。一般socket的缓冲区大小是8K,但都提供API来设置缓冲区的大小(SetSockOpt)。一般发送UDP最好不要超过512字节,这样基本可以保证不丢包(因为大部分网络和主机的MTU都大于512).
2) TCP/IP内核的限制。可能存在一些实现特性使得IP长度不能达到65535。

由于IP能够发送或接收特定长度的数据报并不意味着接收应用程序可以读取该长度的数据。因此,UDP编程接口允许应用程序指定每次返回的最大字节数。如果接收到的数据报长度大于应用程序所能处理的长度,那么会发生什么情况呢?典型的Berkeley版socket API对数据报进行截断,并丢弃任何多余的数据;SVR4下的socket API(包括Solaris 2.x) 并不截断数据报。超出部分数据在后面的读取中返回。它也不通知应用程序从单个UDP数据报中多次进行读取操作;TLI API不丢弃数据。相反,它返回一个标志表明可以获得更多的数据,而应用程序后面的读操作将返回数据报的其余部分。

UDP不会分片,分片是IP层做的事,而且分片重组也是IP层负责的。
如果用UDP发送数据,数据量最好不要太大,应该避免IP层和链路层分包,防止分片丢失,导致整个UDP数据包丢失。追问

TCP就会自己分片,UDP不会吗?
我刚才试了一下在局域网内用udp传送大文件,我的网络MTU是1500,我分别试了应用程数据每次发送1024字节和32K字节,发现32K字节发送的速度是1K字节的3倍多,而且两个传送结果都正确。

如果担心IP层和链路层丢包的话,似乎每次发送1K应该会更快一些,因为不容易丢包,而且每次发送32K,到了IP层照样会分片,也没有一次多发的优势,那怎么会32K的传送更快呢?

追答

你现在做的实验室在局域网环境下,丢包率会很低。
你每次发送1024和32K,对于IP层来说区别不大,一个是1024+UDP包头+TCP包头,一个是1500左右,当在应用层有区别,比如读写文件的次数,这个很耗时间的,还有用户态和内核态切换也需要耗时。

如果你把实验放在Internet环境下,结果会大不相同,32k肯定会大量丢包,不得不在应用层重传,速度你就能想象了。

追问

在TCP时是不是不需要考虑应用层数据大小的问题,因为TCP会自己分片,而且有确认机制,丢包重传也只是一个TCP包的重传?

我用UDP接收的时候发现在应用层总是收够发送方发送的数据,比如发送32K,那么接收就是一次接收32K,而在TCP时一次最多只能接收MTU-包头的数据大小,UDP总是能够完整得接收到一个报文吗?

追答

如果用TCP就不需要考虑数据大小的问题了,数据都是以流的形式发送,是有序的。
这里需要纠正一下,用TCP接受数据,不是一次只能接收MTU-包头的数据大小,其实情况是,每次接受到的数据跟网络状况,以及接受缓冲区大小都有关,现在遇到的情况是,接收方比发送方快。

总之,TCP是流的形式,发送方和接收方是异步的,有可能发送方多次发送的数据包又接收方一次接受,也有可能发送方一次的发送数据,由接收方分多次接受。

用UDP发送数据包的话,发送端发多大的数据包,如果没有错误,接收端也会接收到相同大小的数据包。

来自:求助得到的回答
温馨提示:答案为网友推荐,仅供参考
相似回答