解读TCP/UDP数据包(二):TCP数据包结构

1、图

TCP数据包由首部和数据组成,

每行4个字节(32位)

其中首部最少20个字节(5行),最多60个字节(15行),选项部分是可选的;

TCP首部并没有字段表明整个数据包的长度,是因为TCP数据包是包含在IP数据包中的,而IP数据包已有长度字段,除去IP首部和TCP首部,剩余部分就是TCP包的净荷数据。

解读TCP/UDP数据包(二):TCP数据包结构_第1张图片

解读TCP/UDP数据包(二):TCP数据包结构_第2张图片

2、首部固定部分

1、  第一行:源端口2字节,目的端口2字节

表示发送方和接收方的端口号

 

2、  第二、三行:序列号4字节,确认号4字节

序列号是指该报文段在发送方数据字节流中的位置,在TCP字节流中,每个数据字节都被编号;

确认号是指本机希望收到的下一个字节的序号;

序列号和确认号分别对应报文发送方向和相反方向的数据流;

报文被分解成多个报文段时,序列号就是首字节在整个报文中的偏移量,确认号指定下一个期待的字节;

序列号和确认号的最大表示范围均为2^32-1=4294967295≈42.9亿;

 

3、  第四行:首部长度4位,保留6位,标志位6位,窗口大小16位

首部长度:

        指明首部共有多少行(每行4个字节),则TCP首部的最大长度为(2^4-1)*4=60字节;

标志位6位,含义分别如下:

        URG:紧急指针有效

        ACK:确认序号有效

        PSH:接收方尽快将这个报文段交给应用层

        RST:重建连接

        SYN:同步序号用来发起一个连接

        FIN:发端完成发送任务

窗口大小:

        即发送数据的窗口大小,告诉对方在不等待确认的情况下,可以发来多大的数据;这里表示的最大长度是2^16-1=65535,如需要使用更大的窗口大小,需要使用选项中的窗口扩大因子选项;

 

4、  第五行:TCP校验和16位,紧急指针16位

TCP校验和:【待补充】

紧急指针:

        当URG标志为1时紧急指针才有效,紧急指针是一个正的偏移量,和序号字段中的值相加表示紧急数据最后一个字节的序号(即序列号到紧急指针之间的数据为紧急数据,后面的数据才是正常数据)。

3、首部选项部分

第六行开始是选项部分:

每个选项的开始是1字节的kind字段,说明选项的类型。(这里描述的长度,包含kind和长度字节本身)。

1、kind=0:选项表结束(共1字节)

2、kind=1:无操作(共1字节)Nop:no operation

        用于填充选项字段,使TCP首部长度为4字节的倍数;

3、kind=2:最大报文段长度(共4字节=1+1+2)MSS(Maxinum Segment Size)

        第一个字节:kind的值,即0x02;

        第二个字节:该段选项的长度,即0x04;

        第三四字节:MSS的值,最大报文段长度(仅仅是净荷数据,不包括TCP首部字段);

        TCP包最大净荷数据量为65495(=IP数据包最大长度65535-TCP包头20字节 - IP包头20字节);

        用于发送方与接收方协商最大报文段长度。TCP在三次握手中,每一方都会通告期望收到的MSS(MSS只出现在SYN数据包中),如果一方不接受另一方的MSS值,则使用默认的536字节净荷数据,即主机能够接受20+536字节的TCP报文段。

4、kind=3:窗口扩大因子(共3字节=1+1+1)Window Scaling

        第一个字节:kind的值,即0x03;

        第二个字节:该段选项的长度,即0x03;

        第三个字节:移位值(Shift count)S,表示把窗口值向左移动S位,得到实际窗口大小,移位值的取值范围是0~14,则窗口最大值为1GB,即65535*(2^14)=1073725440=10亿字节=1GB,在TCP建立连接时协商的。如果窗口已经扩大,当不再需要扩大时,发送S=0选项就可以恢复窗口大小到16位;(最大值14,即最大TCP序号限定为2^16 * 2^ 14 = 2^30 < 2^31。该限制用于防止字节序列号溢出。)

        窗口扩大选项是在TCP建立之初进行协商,如果已实现了窗口扩大,当不再需要扩大窗口时,发送移位值=0就可以恢复到原窗口大小,即65535。

5、kind=8:时间戳选项(共10字节=1+1+4+4)Timestamps

        第一个字节:kind的值,即0x08;

        第二个字节:该段选项的长度,即0x0a;

        第三到第六字节:时间戳,系统启动时开始记数(可能是每500毫秒加1),用于计算RTT和防止回绕序号(PAWS);

        第七到第十字节:回送的时间戳,为收到的上一个报文的时间戳;

        时间戳选项用来计算往返时间RTT,发送方在发送报文段时把当前时钟的时间值放入时间戳字段,接收方将该时间戳字段的值复制到确认报文中,当接收方收到确认报文,对比确认报文的时间戳(等于发送方发送报文段的时间戳)和现在的时钟,即可算出RTT。

        时间戳选项还可用于防止回绕序号PAWS。序列号只有32位,每2^32个序列号就会回绕(想想环形队列),采用时间戳选项很容易区分相同序列号的报文段。

6、kind=4:选择确认选项SACK Selective Acknowledgements

        第一个字节:kind的值,即0x04;

        第二个字节:该段选项的长度;

        考虑这样情况,主机A发送报文段12345,主机B收到135且报文无差错,SACK用来确保只重传缺少的报文段,而不是重传所有报文段。

        SACK选项需要2个功能字节,一个用来指明使用SACK选项(SACK Permission),另一指明这个选项占多少字节。

        那怎么形容丢失的报文段2,说明2的左右边界分别是1、3。TCP的数据报文是有字块边界的,而这种边界是由序列号表示的。

        最多能指明多少个字节块的边界信息呢?答案是4个。这是因为选项字段最大是40字节,去除2个功能字节,序列号是32位即4字节,并且需要左右边界,所以(40-2)/8 = 4。

 

4、数据

TCP首部结束之后的部分

------------------------------------

转载请注明出处,谢谢。

小方的专栏

你可能感兴趣的:(网络编程)