为什么UDP最大段大小远远大于此输出中的TCP最大段大小?

时间:2011-08-14 21:18:49

标签: networking network-programming

我尝试使用以下代码来查找TCP和UDP套接字中的最大段大小。我可能错了,因为我正在使用IPPROTO_TCPTCP_MAXSEG作为SOCK_DGRAM,但我得到了一个值,我想知道原因。

if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    perror("cant create socket");

aopt = sizeof(optval);
getsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG, (char *)&optval, &aopt);
printf("tcp max segment size is=%d\n", optval);

输出:

tcp max segment size is=536

然后我尝试使用UDP套接字:

if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    perror("cant create socket");

aopt = sizeof(optval);
getsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG, (char *)&optval, &aopt);
printf("udp max segment size is=%d\n", optval);

输出:

udp max segment size is=134514139

4 个答案:

答案 0 :(得分:3)

TCP有段,UDP有数据报。 UDP数据报长度受UDP数据报长度头字段的大小限制(它是16位)。

来自维基百科:

A field that specifies the length in bytes of the entire datagram: header and data.
The minimum length is 8 bytes since that's the length of the header.
The field size sets a theoretical limit of 65,535 bytes
(8 byte header + 65,527 bytes of data) for a UDP datagram.
The practical limit for the data length which is imposed by the underlying
IPv4 protocol is 65,507 bytes (65,535 − 8 byte UDP header − 20 byte IP header).

检查getsockopt的返回值,UDP没有tcp段,所以肯定会返回错误。

答案 1 :(得分:2)

我确信getsockopt实际上失败了(并返回你忽略的非零状态),所以你打印垃圾(可能你没有初始化optval)。

修改

UDP没有MSS。数据报的最大大小受到许多因素的限制(操作系统如何发送大数据报)。硬限制是IP可以承载的大小。 IP有16b Total Length字段。所以我猜测操作系统是否允许你,65535 - iphdr是数据报的最大大小。

答案 2 :(得分:2)

没有“UDP的最大段大小”这样的东西,因为UDP没有段或MSS。根据yi_H的答案,最大可能的UDP数据报有效载荷大小为65535-28 = 65507。在实践中,它进一步受到NIC的MTU和中间路由器的限制,其方式与TCP的MSS完全相同,但它在路径的长度上协商,就像TCP MSS一样;因此,UDP堆栈不知道它;因此,您无法通过任何API使用它。

答案 3 :(得分:0)

我认为您获得的UDP值是因为您使用的是 level 和选项,它们不适用于TCP的UDP BUT 。您需要按以下方式使用getsockopt

$data  = Model::whereRaw(<condition 1>);
$data_cloned = $data->replicate();
$data1 = $data->whereRaw(<condition 2>);
$data2 = $data_cloned->whereRaw(<condition 3>);
return $data1->toSql();

检查this Microsoft page about the function