TCP数据包何时在应用层被分段?从应用程序发送TCP数据包时,应用程序层的收件人是否会以两个或多个数据包接收数据包?如果是,那么什么条件会导致数据包被分割。似乎数据包在到达以太网(网络层)限制为1500字节之前不会被分段。但是,这个碎片对应用层的接收者是透明的,因为网络层会在将数据包发送到下一层之前重新组合碎片,对吧?
答案 0 :(得分:36)
当它击中具有较低MTU然后数据包大小的网络设备时,它将被拆分。大多数以太网设备都是1500,但它通常可以更小,1492如果因为额外的路由信息,以太网通过PPPoE(DSL),如果添加第二层,如Windows Internet连接共享,则更低。拨号通常是576!
一般情况下,您应该记住 TCP不是数据包协议。它使用最低级别的数据包通过IP进行传输,但就任何TCP堆栈的接口而言,它是一种流协议,并不要求为发送或接收的物理数据包提供1:1的关系。 (例如,大多数堆栈将保留消息,直到某个特定时间段到期,或者有足够的消息来最大化给定MTU的IP数据包的大小)
例如,如果您发送了两个“数据包”(调用您的发送功能两次),接收程序可能只接收1个“数据包”(接收TCP堆栈可能将它们组合在一起)。如果您正在通过TCP实现消息类型协议,则应在每条消息的开头(或其他一些页眉/页脚机制)中包含一个标头,以便接收方可以将TCP流拆分回单个消息,或者在消息中收到的部分是两部分,或者当收到几条消息作为一个块时。
答案 1 :(得分:16)
碎片应该对TCP应用程序透明。请记住,TCP是一种流协议:您获得的是数据流,而不是数据包!如果您基于完整数据包的构思构建应用程序,那么除非您添加抽象层以从流中组装整个数据包然后将数据包传递给应用程序,否则您将遇到问题。
答案 2 :(得分:11)
这个问题假设不是真的 - TCP不会将数据包传递到其端点,而是发送一个字节流(八位字节)。如果应用程序将两个字符串写入TCP,则可以在另一端将其作为一个字符串传递;同样地,一根弦可以作为另一端的两根(或更多根)弦传送。
RFC 793,第1.5节:
“TCP能够转移 每个连续的八位字节流 用户之间的方向 包装一些八位字节 细分通过传播 互联网系统。“
关键词是连续的八位字节流(字节)。
RFC 793,第2.8节:
“没有必要的关系 推送功能和段之间 边界。任何特定的数据 细分可能是单一的结果 发送电话,全部或部分或 多个SEND电话。“
第2.8节的全部内容是相关的。
答案 3 :(得分:5)
在应用层,有许多原因可能导致整个1500字节无法显示一个读取。内部操作系统和TCP堆栈中的各种因素可能导致应用程序在一次读取调用中获取一些字节,而另一些则在下一次调用中获取一些字节。是的,TCP堆栈必须在发送之前重新组装数据包,但这并不意味着你的应用程序将一次性完成所有这一切(它可能会在一次读取中获得它,但它并不保证在一次阅读中得到它。)
TCP尝试保证按顺序传送字节,并在您的背后发生错误检查,自动重新发送等。可以把它想象成应用层的管道,不要陷入堆栈实际通过网络发送它的过程中。
答案 4 :(得分:2)
如果数据包超过网络设备的最大MTU,它将被分解为多个数据包。 (注意大多数设备设置为1500字节,但这不是必需的。)
数据包的重建应该对应用程序完全透明。
答案 5 :(得分:2)
不同的网段可以具有不同的MTU值。在那种情况下,可能发生碎片化。有关详细信息,请参阅TCP Maximum segment size
此(de)碎片发生在TCP层中。在应用程序层中,没有更多的数据包。 TCP向应用程序提供连续的数据流。
答案 6 :(得分:2)
“应用程序层”是一个TCP数据包(好吧,真正的段;它自己层的TCP不知道来自数据包)永远不会被分段,因为它不存在。您可以在应用程序层中将数据视为字节流,并按顺序可靠地传递。
如果你正在考虑它,你可能会以错误的方式接近某些事情。但是,这并不是说在这个可能的有序字节流上传递的消息序列之上可能没有一层。
答案 7 :(得分:2)
This页面是关于其他人提出的一些问题的良好信息来源,即应用程序协议基础上对应用程序协议进行数据封装的必要性在您所描述的意义上并不具有权威性,但它有一些例子,并且是网络编程中的一些非常大的名字。
答案 8 :(得分:1)
正确 - 提供信息最丰富的方式是使用Wireshark,这是一个非常宝贵的工具。花点时间搞清楚 - 已经多次保存了我,并给出了一个很好的现实检查
答案 9 :(得分:0)
如果一个3000字节的数据包进入一个默认MTU大小为1500(以太网)的以太网网络,它将被分段为每1500字节长度的两个数据包。这是我唯一能想到的。
Wireshark是您查看此内容的最佳选择。我已经使用了一段时间并且给我留下了深刻的印象