37

TCP 数据包何时会在应用层分片?当一个应用程序发送一个 TCP 数据包时,应用程序层的接收者会收到两个或多个数据包中的数据包吗?如果是,是什么条件导致数据包被分割。似乎一个数据包在达到 1500 字节的以太网(在网络层)限制之前不会被分段。但是,由于网络层会在将数据包发送到下一层之前重新组装这些碎片,因此该碎片对于应用层的接收者来说是透明的,对吧?

4

10 回答 10

39

当它遇到 MTU 低于数据包大小的网络设备时,它将被拆分。大多数以太网设备是 1500,但它通常可以更小,例如 1492,如果该以太网由于额外的路由信息​​而通过 PPPoE (DSL),如果添加第二层,例如 Windows Internet 连接共享,它甚至会更低。而拨号一般是576!

一般来说,尽管您应该记住TCP 不是数据包协议。它使用最底层的数据包通过 IP 传输,但就任何 TCP 堆栈的接口而言,它是一个流协议,不需要为您提供与发送或接收的物理数据包的 1:1 关系(例如,大多数堆栈将保留消息直到某个时间段到期,或者有足够的消息来最大化给定 MTU 的 IP 数据包的大小)

例如,如果您发送了两个“数据包”(调用您的发送函数两次),接收程序可能只收到 1 个“数据包”(接收 TCP 堆栈可能将它们组合在一起)。如果您通过 TCP 实现消息类型协议,则应在每条消息的开头包含一个标头(或其他一些标头/页脚机制),以便接收方可以将 TCP 流拆分回单独的消息,无论是当消息分两部分接收,或者当多个消息作为一个块接收时。

于 2009-04-16T16:05:29.790 回答
17

分片对 TCP 应用程序应该是透明的。请记住,TCP 是一种流协议:您得到的是数据流,而不是数据包!如果您基于完整数据包的概念构建应用程序,那么您将遇到问题,除非您添加一个抽象层来组装来自流的整个数据包,然后将数据包传递给应用程序。

于 2009-04-16T16:06:52.533 回答
12

这个问题做了一个不正确的假设——TCP 不会将数据包传送到它的端点,而是发送一个字节流(八位字节)。如果应用程序将两个字符串写入 TCP,它可能会在另一端作为一个字符串传递;同样,一个字符串可以作为两个(或更多)字符串传递到另一端。

RFC 793,第 1.5 节:

“通过将一些八位组打包成段以通过互联网系统传输,TCP 能够在其用户之间的每个方向上传输连续的八位组流。”

关键词是八位字节(字节)的连续流。

RFC 793,第 2.8 节:

“推送功能和段边界之间没有必然的关系。任何特定段中的数据可能是单个 SEND 调用的结果,全部或部分,或多个 SEND 调用的结果。”

2.8 节的全部内容都是相关的。

于 2010-04-20T20:50:59.117 回答
5

在应用层,有很多原因导致整个 1500 字节可能无法显示一次读取。内部操作系统和 TCP 堆栈中的各种因素可能会导致应用程序在一次读取调用中获取一些字节,而在下一次读取调用中获取一些字节。是的,TCP 堆栈必须在发送数据包之前重新组装数据包,但这并不意味着您的应用程序会一次性获得所有数据(很可能会一次读取,但不能保证一口气读完)。

TCP 试图通过错误检查、自动重新发送等来保证字节的有序传递,等等。把它想象成应用层的管道,不要太纠结于堆栈实际上是如何通过网络发送它的。

于 2009-04-16T15:59:22.567 回答
2

如果一个数据包超过了网络设备的最大MTU,它将被分成多个数据包。(注意大多数设备设置为 1500 字节,但这不是必需的。)

数据包的重建对应用程序应该是完全透明的。

于 2009-04-16T15:53:09.290 回答
2

不同的网段可以有不同的 MTU 值。在这种情况下,可能会出现碎片。有关详细信息,请参阅TCP 最大段大小

这种(去)碎片化发生在 TCP 层。在应用层没有更多的数据包。TCP 向应用程序提供一个连续的数据流。

于 2009-04-16T15:54:54.933 回答
2

“应用层”一个 TCP 数据包(嗯,真的是分段;TCP 在它自己的层不知道数据包)永远不会分段,因为它不存在。应用层是您将数据视为字节流的地方,可靠且有序地传递。

如果您不考虑它,那么您可能以错误的方式处理某些事情。然而,这并不是说在此之上可能没有一层,例如,通过这个可靠的有序字节流传递的消息序列。

于 2009-06-06T06:44:19.513 回答
2

页面是有关其他人提出的一些问题的良好信息来源,即需要基于应用程序协议在应用程序协议上进行数据封装在您描述的意义上不是很权威,但它有示例并且来自一些网络编程中的大牌。

于 2010-04-28T23:36:03.937 回答
1

正确 - 了解这一点的最有用的方法是使用Wireshark,这是一个非常宝贵的工具。花点时间弄清楚 - 救了我好几次,并提供了一个很好的现实检查

于 2009-04-16T15:53:30.660 回答
0

如果一个 3000 字节的数据包进入默认 MTU 大小为 1500(对于以太网)的以太网网络,它将被分成两个长度为 1500 字节的数据包。这是我唯一能想到的。

Wireshark 是检查这一点的最佳选择。我已经使用了一段时间并且印象深刻

于 2009-04-16T15:52:47.357 回答