TCP连接的最大数据包大小

233

TCP连接的最大数据包大小是多少,或者我如何获取最大数据包大小?


27
TCP是基于流的。你为什么要担心个别数据包? - Matti Virkkunen
34
因为下层是基于数据包的……典型实现-> 第1层 - 以太网物理层,第2层 - 以太网介质访问控制层(MAC协议数据单元定义),第3层 - 网际协议(IP协议数据单元定义),第4层 - 传输控制协议(TCP)- 使用其下基于数据包的服务。 - user656925
8
“TCP包”这个说法并不准确。实际上,有TCP“段”,其长度由32位字描述,并且它们被包含在或跨越16位描述长度的IP数据包中。此外,还有以太网帧,其中包含所有这些内容。您需要翻译的是这些内容中的哪一部分?无论如何,如果使用TCP,则无需以任何方式担心它们:TCP和IP会为您处理一切。 - user207421
以太网(互联网)连接属性在Windows中某些时候显示的是数据包的活动统计信息,而不是发送/接收字节。没有快速更改视图的选项。这就需要直接输出数据包大小。 - master-lame-master
10个回答

213

TCP数据包的绝对限制大小为64K(65535字节),但实际上这比您将看到的任何数据包的大小都要大得多,因为较低层(例如以太网)的数据包大小更小。

例如,以太网的MTU(最大传输单元)为1500字节。一些类型的网络(如令牌环)具有更大的MTU,而某些类型则具有较小的MTU,但每种物理技术的值都是固定的。


24
“但是每种物理技术的值都是固定的”——这并不正确。以太网过去最大的 MTU 是 1500,但您可以使用更低的值。随着巨型帧的出现,实际上没有指定的最大值,且最大值取决于硬件和驱动程序。 - WhirlWind
4
@Whirl: 是的,它们是可配置的,但通常情况下不会被配置;"可配置"是主观的,因为需要深入内核才能这样做。这不是在应用程序级别可以随意调整的东西,而OP似乎正处于这个级别。 - Ether
3
@HiroProtagonist说:“1500是一个最大值,所以只有600也不足为奇。” - Nicolas Raoul
40
为什么数据包大小限制为64K(65535字节)?因为TCP头中的窗口大小属性只有16位。我只是想提一下,这可能会在某个时候帮助到某人......顺便说一句,@Ether的回答很好! - Cacho Santa
2
此外,使用窗口缩放可以提高它的速度。在这种情况下,最大值为1 GiB。 - Martin Melka
显示剩余11条评论

99
这是一个非常好的问题,我在工作中确实经常遇到这个问题。有很多"技术上正确"的答案,比如65k和1500字节。我做了很多写网络接口并使用65k字节的工作,而且使用1500字节也可能会遇到大麻烦。我的工作涉及到很多不同的硬件/平台/路由器,老实说我开始使用的大小是1400字节。如果你需要的字节数超过1400,你可以逐渐增加字节数,可能可以增加到1450或者大约1480?如果你需要更多的话,当然你需要将数据分成两个数据包,这有几种明显的方法可以实现...
问题在于你要创建一个数据包并通过TCP写出它,但是当然还有附加的头数据等,因此你需要"携带"一些数据,将你的总大小增加到1500甚至更多...而且很多硬件的限制更低。
如果你"强行推进",就可能会发生一些非常奇怪的事情。显然会截断数据,很少见到丢失数据。数据损坏也很少但肯定会发生。

1
为什么 GET 请求平均约为 600 字节? - user656925
12
你的意思是64K而不是65K。我不知道你所说的“我开始的位置是1400字节”是什么意思。你不必担心TCP API中的数据包大小,它会自动确定和遵守路径MTU。如果方便的话,完全可以在一个'send()'中写入2G的数据。 - user207421
29
你的 1480 左右 应该改成 1460。IP 头和 TCP 头至少各占用 20 字节(除非使用了可选的头部字段),因此在(非巨型帧)以太网中,最大传输单元为 1500 - 20 - 20 = 1460 - Evgeniy Berezovsky
3
我通过使用wireshark看到一个服务器发送了大数据包(超过1400字节),而客户端将其拆分为多个大小为1400字节的小数据包接收。是谁负责拆分数据包的?@Nektario……? - inbaly
3
@EugeneBeresovsky,使用可选标头会增加40个字节,但是它是可变的,因此1420应该是极限。建议使用1400可以获得一些填充。我会选择1408,因为它可以被128整除。 - That Realty Programmer Guy
显示剩余2条评论

26
在应用程序层面上,该应用程序使用TCP作为面向流的协议。TCP又将其抽象为段并摒弃了使用不可靠IP数据包的详细信息。
TCP处理的是段而不是数据包。每个TCP段都有一个序列号,该序列号包含在TCP头中。在TCP段中发送的实际数据是可变的。
有一个名为getsockopt的值在某些操作系统上得到支持,您可以使用它来检索最大TCP段大小(MSS)。但并非所有操作系统都支持它。
我不确定您想要做什么,但如果要减小使用的缓冲区大小,还可以查看:SO_SNDBUF和SO_RCVBUF。

我想知道如果你可以将所有消息放入一个大的TCP数据包中,是否可以将TCP用作消息队列? - CMCDragonkai

9

TCP API 中没有数据包。

通常底层协议中会有数据包,例如当 TCP 在 IP 上完成时,你可能对它们没有兴趣,因为除了非常微妙的性能优化之外,它们与用户无关(根据问题的表述)。

如果你问一次 send() 调用可以发送的最大字节数是多少,则这取决于实现和设置。通常,你会调用 send() 发送几千字节的数据块,并始终准备好系统完全或部分拒绝接受它的情况,在这种情况下,你将必须手动将数据拆分成较小的块,以将其馈送到 TCP send() API 中。


10
TCP有数据包和数据包头,其中一部分与IP头重叠。虽然你不应该看到它,但这并不意味着它不存在。TCP始终在IP上进行。由于头部重叠,如果没有IP,你就无法使用TCP。 - WhirlWind
27
TCP有"数据段",IP有数据包。 - user207421
4
TCP有分段(或称之为数据包,都可以)。TCP API没有数据包。 - Pavel Radzivilovsky
19
@NathanLong的意思是造成了不必要的混淆。TCP有段(segments),UDP有数据报(datagrams),IP有数据包(packets),以太网有帧(frames),... - user207421
2
@Chexxor,那么你打算用什么语言来描述以太网帧内IP数据包中的TCP段?完全没有必要通过使用相同的术语来描述不同的事物来混淆问题,因为这些事物的作者已经费尽心思使用不同的术语。 - user207421
显示剩余2条评论

8

5
通常,这取决于连接使用的接口。您可以使用ioctl()获取MTU,如果是以太网,您通常可以通过从硬件标头大小中减去14来获得最大数据包大小,这是没有VLAN的以太网的情况。
只有在整个网络的MTU至少达到该大小时才适用。 TCP可能会使用路径MTU发现来减小有效MTU。
问题是,您为什么要关心?

7
这只能让你在第一个链接上获得最大数据包大小。据我所知,路径中的任何其他节点都可以选择不支持大数据包,并且数据包可能会在途中的任何位置被分割。 - Matti Virkkunen
是的,那是正确的...所以你的问题很好 - 为什么你想要这个? - WhirlWind
我想通过局域网连接传输视频/图像。 - Alexa
2
由于TCP是面向流的,这为什么很重要? - WhirlWind

4

如果您使用的是Linux机器,“ifconfig eth0 mtu 9000 up”是设置接口MTU的命令。但是,我必须指出,如果网络传输不够稳定,则大MTU会有一些缺点,并且可能会使用更多内核空间的内存。


3
一种解决方案是设置套接字选项TCP_MAXSEG(http://linux.die.net/man/7/tcp)为一个与底层网络“安全”的值(例如,在以太网上设置为1400为安全值),然后在发送系统调用中使用大缓冲区。这样可以减少昂贵的系统调用。内核将把数据分割以匹配MSS。
这样,您可以避免截断数据,而您的应用程序也不必担心小缓冲区。

3
似乎大多数互联网上的网站将MTU值设为1460字节。有时是1452,如果您使用VPN,它将进一步降低IPSec头的大小。
默认窗口大小差异很大,最大可达65535字节。我使用http://tcpcheck.com查看自己的源IP值并检查其他互联网供应商正在使用什么。

3
在IP协议(IPv4)中,TCP设置的数据包大小。对于该字段(TL),分配了16位,因此数据包的最大大小为65535字节:IP协议详细信息

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