报文段.是指
TCP/IP协议网络传输过程中,起着路由导航,查询各个网络路由网段,IP地址,交换协议等IP数据包。报文段充当整个TCP/IP协议数据包的导航路由功能。
TCP提供的是一种面向连接的,可靠的
字节流服务,TCP提供可靠性的一种重要的方式就是MSS。通过MSS,应用数据被分割成TCP认为最适合发送的
数据块,由TCP传递给IP的信息单位称为报文段或段(
segment)。代表一个TCP socket的结构体struct
tcp_sock中有多个成员用于确定应用数据被分割成最大为多大的
数据块较为合适(最大报文段长度MSS)。
我们不难联想到,跟最大报文段长度最为相关的一个参数是网络设备接口的
MTU,
以太网的MTU是1500,基本IP首部长度为20,TCP首部是20,所以MSS的值可达1460(MSS不包括协议首部,只包含应用数据)。
前面的TCP
三次握手协议中我们看到,通讯的双方都通过TCP选项通告了自己期望接收的MSS值,该值直接来源于struct tcp_sock的成员advmss,而这个值直接取自于网络设备接口的MTU减去IP首部和TCP首部的长度。在本地
以太网中可达1460(如果首部都不含选项的话)。而成员rx_opt是一个
结构体struct
tcp_options_received,它记录的是来自对端的TCP选项通告,其成员mss_clamp表示mss的上限值,其来源就是对端的MSS 通告,而mss_user是用户设置的mss,其优先级最高,如果有user_mss,则使用user_mss,忽略其它。
从上面我们可以看到,MSS是可以通过SYN段进行协商的(MSS选项只能出现在SYN报文段中),但它并不是任何条件下都可以协商的,如果一方不接受来自另一方的MSS值,并且没有user_mss,则MSS就定为默认值536字节(加上首部,允许576字节的
IP数据报)。实际上,struct tcp_sock→rx_opt→mss_clamp的初始值就定为536,等收到来自对端的MSS通告后,才进行修改。而
结构体 struct tcp_sock的成员mss_cache用于缓存上次的有效的mss,其初始值也被定为536。
函数my
tcp_sync_mss为一个tcp socket中的mss相关的成员进行数据同步,其基本的一个算法是:
所以,说本地
以太网中MSS为1460的说法并不正确,它还会动态变化,如果IP首部和TCP首部中出现选项,则MSS要相应的减小,一般TCP首部中会有12字节的
时间戳选项(外加两字节的填充选项),这时的MSS就等于1448。
MSS的主要作用是限制另一端
主机发送的数据的长度,同时,主机本身也控制自己发送数据报的长度,这将使以较小MTU连接到一个网络上的主机避免分段。
struct tcp_sock有一个成员xmit_size_goal,用于记录该socket发送数据报时的
segment的大小,一般情况下它的值就等于MSS(特殊情况有例外,以后再分析)。