zoukankan      html  css  js  c++  java
  • TCP中报文段大小(MSS)、MTU

    一、MSS的含义
    我们知道TCP传输可靠性的保证中有一点是:TCP会将应用层交付下来的数据分为TCP认为最适合发送的数据块。这里的数据块大小就是MSS(maximum segment size最大分段长度)。MSS字段位于TCP首部中的选项字段。

    一句话,MSS就是TCP报文段所允许传送的最大数据部分的长度,如果上层交付下来的数据太大,就对其进行数据分块。这个分块过程是在运输层完成的,在接收端的运输层对分块的TCP报文段的数据部分进行重组。

    注意:这个MSS指的是TCP报文段中数据部分的最大长度,并不是整个TCP报文段长度。整个TCP报文段长度 = TCP首部长度 + TCP数据部分长度。

    二、通信双方如何协商MSS
    MSS的值是在TCP三次握手建立连接的过程中,经通信双方协商确定的。我们都知道链路层使用以太网的话,IP层的MTU是1500 byte,这样去掉IP数据报首部(20 byte),在去掉TCP首部(20 byte)后为1460 byte,此时在默认情况下TCP“选项”字段的MSS值为1460 byte = 1500 - 20 - 20。在 Internet 标准中,IP层的MTU是576 byte,那么此时TCP“选项”字段的MSS值为536 byte = 576 - 20 - 20。

    以上是默认情况下一个TCP报文段中的MSS值,下面我们详细说明MSS值的确定过程。

    MSS值只会出现在SYN报文中(不要问我为什么,我也不知道为什么只出现SYN报文中),即SYN=1时,才会有MSS字段值。当客户端想要以TCP方式从服务器端下载数据时,

    (1)首先客户端会发送一个SYN请求报文,这个SYN报文的“选项”字段中会有MSS值(MSS = MUT - IP首部长度 - TCP首部长度)。该MSS值是为了告知对方最大的发送数据大小。

    (2)当服务器端收到SYN报文后,会向请求端返回SYN+ACK(同步确认报文)报文,其中的“选项”字段也会有MSS值。

    (3)通信双方选择SYN和SYN+ACK报文中最小的MSS最为此次TCP连接的MSS,从而达到通信双发协商MSS的效果。

    综上,可以回答开始时的问题。在第二次握手后就可以确定TCP中最大传输报文(MSS)大小。

    三、MTU
    MTU是最大传输单元,这个根据由具体的网络决定的,如以太网MTU=1500,Internet的MTU=576。

    如果IP层所要传输的数据长度>MTU的话,要对这个数据进行分片处理,每个片长度都小于MTU,每个片构成一个IP数据报进行传输。

    在服务端的IP层使用IP数据报的首部信息对这些分片的IP数据报进行重组。这样使得IP层的分片对传输层看起来是透明的(传输层不知道IP层进行了分片操作)。

    四、MTU分片的一个问题
    (1)如果IP层每个分片都正确到达目的端,那自然是很好的。但是如果IP层在发送端对要发送的数据(TCP报文段)进行分片操作,但是在传输过程中某个分片发生了错误,这样会使整个TCP报文段重传。因为IP层不负责可靠性(超时和重传),可靠性有传输层提供。

    这也是TCP对数据分段的一个原因,分段后的数据在往下交付后肯定不会超过MTU,这样避免了因为分片而带来的的麻烦。

    (2)如果UDP进行数据传输的话,UDP将应用层交付下来的整个数据封装为UDP数据报(没有像TCP分块的操作)。这样IP层的数据很容易超过MTU,造成数据分片。而TCP的数据分块,不会导致IP层的分片。

    总的来说UDP不会分段,就由IP来分片。TCP分段,也就不用IP来分片了!

    总结:

    1、IP分片是由于传输的数据超过了MTU,TCP分块是由于数据超过了MSS。

    2、IP分片是在发送端的网络层中进行的,IP重组是在接收端的网络层中,根据IP首部完成的。TCP数据分块是在发送端的传输层进行的,TCP重组是在接收端的传输层完成的。IP层的分片与重组对传输层是透明的。

    一般情况下,使用UDP、ICMP发送数据时,在网络层要进行分片。而使用TCP传输的话,TCP的MSS分块避免了分片。
    ————————————————
    版权声明:本文为CSDN博主「bian_qing_quan11」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/bian_qing_quan11/article/details/72630354

  • 相关阅读:
    [日常] Go语言圣经-命令行参数
    [日常] Go语言圣经前言
    [日常] 搭建golang开发环境
    [日常] 研究redis未授权访问漏洞利用过程
    [日常] CentOS安装最新版redis设置远程连接密码
    [日常] Apache Order Deny,Allow的用法
    [日常] 读取队列并循环发信的脚本
    [日常] 20号日常工作总结
    [日常] SinaMail项目和技术能力总结
    [日常] MySQL的预处理技术测试
  • 原文地址:https://www.cnblogs.com/zy09/p/14956471.html
Copyright © 2011-2022 走看看