TCP网络数据包在应用层何时会被分段?

38

什么情况下会在应用层分段TCP包?当TCP包从应用程序发送时,接收端是否会收到两个或更多的数据包?如果是这样,是什么条件导致分割数据包。看起来,除非达到以太网(网络层)1500字节的限制,否则包不会被分段。但是,分段将对应用层的接收方透明,因为网络层将在将分段重组后再将数据包发送到下一层,对吗?


2
唯一能在应用层分段 TCP 传输的是应用程序本身。你的问题并没有什么意义。 - user207421
10个回答

40

当数据包的大小大于网络设备的最大传输单元(MTU)时,它会被分割。大多数以太网设备的MTU为1500,但如果该以太网通过PPPoE(DSL)协议发送,由于额外的路由信息,MTU可能会更小,比如1492,甚至更低,例如在添加了第二层网络协议(如Windows Internet Connection Sharing)时。而拨号连接通常只有576!

总的来说,你应该记住TCP不是一个数据包协议。它在最低层使用数据包进行IP传输,但就任何TCP堆栈的接口而言,它都是一个流协议,并没有提供一对一的物理数据包发送或接收的要求(例如,大多数堆栈将消息保留,直到达到一定时间或足够数量的消息才能使给定MTU的IP数据包最大化)。

例如,如果您发送两个“数据包”(调用发送函数两次),接收程序可能只收到1个“数据包”(接收TCP堆栈可能将它们合并在一起)。 如果您正在TCP上实现消息类型的协议,则应在每个消息的开头(或其他标题/尾部机制)包含一个标题,以便接收方可以将TCP流拆分回单独的消息中,无论是在接收到一部分消息时还是在一次接收多个消息时。


实际上,这取决于沿途每一跳的MTU(实际上是最小的MTU)。但对于小负载(如OP问题中的10或20字节),如果整个数据包(包括每个协议层的所有头部,即使是通过VPN添加在顶部的那些)+有效载荷的大小都在ipv4最小尺寸的限制内,它几乎可以确定不会被分段。在http://en.wikipedia.org/wiki/Maximum_transmission_unit上,您可以看到对于ipv4,在跳点上至少保证了最大MTU为68字节(而不是有效载荷!)。 - Olivier Dulac
这里还有一个参数MSS,这里没有提到。 - Maxim Egorushkin

17

分段应该对TCP应用程序透明。请记住,TCP是一种流协议:您会获得数据流,而不是分组!如果您基于完整数据包的概念构建应用程序,则除非添加抽象层来从流中组装整个数据包并将数据包传递给应用程序,否则将会出现问题。


14
问题存在一个不正确的假设——TCP不会将数据包传递到其端点,而是发送一串字节(八位组)。如果应用程序将两个字符串写入TCP,则可能在另一端作为一个字符串传递;同样,一个字符串也可能在另一端被分成两个或多个字符串。 RFC 793,第1.5节:
"The TCP is able to transfer a continuous stream of octets in each direction between its users by packaging some number of octets into segments for transmission through the internet system."
关键词是"continuous stream of octets"(字节)。 RFC 793,第2.8节:
"There is no necessary relationship between push functions and segment boundaries. The data in any particular segment may be the result of a single SEND call, in whole or part, or of multiple SEND calls."
整个第2.8节都是相关的。

5
在应用层,可能有许多原因导致整个1500字节在一次读取中无法显示。操作系统和TCP堆栈内部的各种因素可能会导致应用程序在一次读取调用中获取一些字节,而在下一次读取中获取另外一些字节。是的,TCP堆栈必须在将其发送到上层之前重新组装数据包,但这并不意味着您的应用程序将一次性获得所有内容(虽然很可能会在一次读取中获取所有内容,但不能保证)。
TCP试图保证按顺序传送字节,并进行错误检查、自动重发等操作,这些操作都在后台进行。把它看作是一个应用程序层的管道,不要过于沉迷于堆栈实际如何通过网络发送数据。

3
这篇文章是关于一些问题的信息来源,比如根据应用程序协议的需要进行数据封装等。虽然不像你所描述的那样权威,但其中提供了示例,并引用了一些网络编程方面的大牛的观点。

2
在TCP数据包中,“应用层”(实际上是“段”;TCP在自己的层中并不知道数据包)永远不会被分段,因为它不存在。应用层是您将数据视为按顺序可靠传递的字节流的地方。
如果您以其他方式考虑它,那么您可能正在错误地处理某些内容。但是,这并不意味着上面可能没有一层,例如通过此可靠、有序的字节流传递的消息序列。

2
如果数据包超过网络设备的最大MTU,它将被分成多个数据包。(注意,大多数设备设置为1500字节,但这不是必需的。)
数据包的重构应该对应用程序完全透明。

2
不同的网络段可以有不同的MTU值。在这种情况下,可能会发生分段。有关更多信息,请参见TCP最大分段大小
此(去)分段发生在TCP层。在应用层中没有更多数据包。TCP向应用程序呈现连续的数据流。

1

正确的做法是使用Wireshark这个非常有价值的工具来查看。花点时间去研究它,它曾经帮我解决了很多问题,并且可以提供一个很好的现实检验。


0
如果一个3000字节的数据包进入以太网网络,其默认MTU大小为1500(适用于以太网),它将被分成两个长度为1500字节的数据包。这是我能想到的唯一情况。
Wireshark是检查这个问题的最佳选择。我已经使用它一段时间了,非常印象深刻。

那么,在应用层,接收应用程序会接收到两个数据包还是一个? - zooropa
应用层没有MTU和数据包分段的概念。它是一个与网络层和传输层具有不同职责的单独层。简短来说,应用层无法看到两个数据包。 - Srikar Doddi

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