TCP rfc地址https://www.ietf.org/rfc/rfc793.txt
chapter3 功能描述
3.1 TCP头格式
TCP头格式如下
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |U|A|P|R|S|F| |
| Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
各字段含义
Source Port:16bit,源端口号
Destination Port:16bit,目的端口号
Sequence Number:32bit,若没提供SYN,那么段序列号是第一个字节的序列号,若提供了SYN,那么是初始序列号ISN,第一个字节的序列号是ISN加1
Acknowledgment Number:若设置了ACK标记,那么此字段的值是段发送者希望接收的下一个段的序列号。当一个连接建立之后,此字段永远被发送
Data Offset:4bit,TCP头的32bit字的数量,此字段指示数据开始的位置。无论是否包含options,TCP头是32bit字的整数
Reserved:6bit,保留,必须写全0
Control bits:6bit,从左到右依次是
URG:紧急指针字段标记
ACK:确认字段标记
PSH:推函数
RST:重建连接
SYN:同步序列号
FIN:发送者没有更多数据发送了
Window:16bit,接收者可以接收的数据长度,从acknowledge字段中发送者希望接收的第一个字节开始,单位是8bit字
Checksum:16bit,是TCP头和内容的所有16bit字的补码之和,再取补码得到的一个16bit字的结果。若一个段的头和内容的长度之和是奇数,那么需要补充一个8bit字0,这个补充是不随着报文传送的,是一个软件行为。校验和还包括一个96bit的伪头,作为TCP头的概念前缀。伪头包含源地址、目的地址、协议、TCP长度。这个伪头给TCP提供了误传保护。这个信息被网络协议携带,被IP上的TCP通过TCP网络接口调用,以参数或者返回值的形式传输。伪头格式如下:
+--------+--------+--------+--------+
| Source Address |
+--------+--------+--------+--------+
| Destination Address |
+--------+--------+--------+--------+
| zero | PTCL | TCP Length |
+--------+--------+--------+--------+
其中PTCL是是协议类型,比如TCP是6,UDP是17;TCP Length是TCP头长度加上数据部分长度,不包含12字节的伪头
校验和计算步骤:
发送者:
1.将伪头、TCP头、TCP数据内容看作16bit字,若不足,最后用1个8bit字的0补充
2.将TCP报文中校验和字段填成0
3.将每个16bit字的反码相加,溢出的高位进位到低位,得到一个16bit字的最终结果,填充在TCP报文中的Checksum字段
接收者:
利用反码求和,得到的最终结果应该16bit全是1,否则说明数据有误
一个4bit求和的例子:
发送者:
数据1010 0001 校验和0000
取所有4bit字的反码,得到0101 1110 1111
累加所有反码,得到0010 0010
将溢出的部分作为4bit字,加到低4bit,得到0100,就是校验和,填充在TCP的Checksum字段中
接收者:
数据1010 0001 校验和0100
取所有4bit字的反码,得到0101 1110 1011
累加所有反码,得到0001 1110
将溢出的部分作为4bit字,加到低4bit,得到1111,说明验证OK,数据正确
Urgent Pointer:16bit,这个字段表达紧急指针当前的值,是这个段序列号的正偏移。紧急指针指向的数据部分从偏移的序列号所在的字节开始。只有URG标记被设置的时候,此字段才会被解释
Options:可变长,options在TCP头中占用空间,是8bit字的整数倍。因此所有options都会被纳入校验和的计算之中。一个option可以从任何字节边界开始。有两种option格式可以使用:
1.一个字节表达option种类
2.一个字节表达option种类,一个字节表达option长度,然后跟随实际数据长度
第一种格式用于一个控制标记,只需要1个字节就可以被识别,第二种方式是包含数据的option格式,其中option长度字段包含表达option种类和option长度的两个字节,加上实际数据长度。
注意,options可能没那么多,导致比data offset字段中说明的头结束的位置短,那么从option结束到头结束的这段空间必须填充0
TCP必须实现所有options。当前定义的option如下(八进制表示)
Kind Length Meaning
---- ------ -------
0 - End of option list.
1 - No-Operation.
2 4 Maximum Segment Size
具体定义如下:
Kind0:8bit全0,表示option列表结束。此字段可能不和Data Offset字段中指出的TCP头结尾一致,这时候用0填充不足的部分。注意这个字段表示的是所有option结束而不是一个option结束,并且只有option列表结束和TCP头结束不一致的时候,才会使用到这个字段
Kind1:0000 0001,此字段可能在option之间使用,例如,排列一个接下来的option到字边界。由于不保证发送者一定使用这个字段,因此接收者需要准备好处理不在字边界开始的option
Kind2:0000 0010 0000 0100 xxxx xxxx xxxx xxxx,表示最大段长度,第一个字节表达kind是2,第二个字节是总长度,可以得出数据部分的长度是2字节,用这2个字节的16bit表示最大段长度,表示发送者能接受的最大TCP段长度。当且仅当在初始化TCP连接请求的时候(携带STN标记的TCP报文),发送这个option。若初始化的时候,没有这个option,那么多大的段都会被发过来。
Padding:可变长,这个字段用来保证TCP头结束、也就是数据开始的地方是从32bit边界开始的,用全0填充
3.2 术语
为了保持TCP连接需要保存一些变量。想象这些变量被连接控制块TCB的连接记录保存,TCB中保存的变量是本地和远端socket号、安全、连接优先级、指向应用层发送和接收缓存的指针、指向重传队列和当前段的指针。除此之外,一些和发送、接收序列号相关的变量也在TCB中保存。
发送队列变量如下:
SND.UNA:已经发送但是没收到对端ack的
SND.NXT:将要发送的
SND.WND:发送窗口
SND.UP:发送紧急指针
SND.WL1:最后一次更新窗口的段的序列号
SND.WL2:最后一次更新窗口的段的ack号
ISS:初始发送序列号
接收队列变量如下:
RCV.NXT:将要接受的
RCV.WND:接受窗口
RCV.UP:接受紧急指针
IRS:初始接受序列号
发送队列空间:
1 2 3 4
----------|----------|----------|----------
SND.UNA SND.NXT SND.UNA
+SND.WND
1:已经被ack的旧的序列号
2:尚未ack的序列号
3:允许新的数据传输的序列号
4:尚未被允许的未来序列号
图中,序列号按照从小到大的顺序排成一列,SND.UNA截断的部分是之前发送并且已经被对端ack的,也就是第一部分。第二部分是已经发送但是对端没有ack的,被SND.NXT截断。第二部分和第三部分之和是发送窗口,剩余窗口也就是目前可以发送的最大字节数在第三部分。最后的第四部分就是窗口之外的
接收队列变量:
1 2 3
----------|----------|----------
RCV.NXT RCV.NXT
+RCV.WND
1:已经被ack的旧的序列号
2:允许接收的序列号
3:尚未被允许的未来序列号
其中,已经ack的序列号被RCV.NXT截断,在第一部分。第二部分是接收窗口。第三部分是接收窗口之外的部分
除了发送和接收变量之外,还有一些变量被频繁使用,它们从当前段中取值,当前段变量如下:
SEG.SEQ:段序列号
SEG.ACK:段ack号
SEG.LEN:段长度
SEG.WND:段窗口
SEG.UP:段紧急指针
SEG.PRC:段优先级
一个连接过程在其生命周期中经历若干状态。状态包括:LISTEN,SYN-SENT,SYN-RECEIVED,ESTABLISHED,FIN-WAIT1,FIN-WAIT2,CLOSE-WAIT,CLOSING,LAST-ACK,TIME-WAIT,以及一个虚构的最终状态CLOSED。CLOSED状态是虚构的因此它代表的状态已经没有TCB了,同样已经没有连接了。每个状态具体含义如下:
LISTEN:等待任何远端TCP和端口发来的连接请求
SYN-SENT:在发送一个连接请求之后,等待一个匹配的连接请求
SYN-RECEIVED:在发送和接收到连接请求之后,等待确认连接请求
ESTABLISHED:连接已经建立,可以接受数据并分发给应用层,是数据传输阶段的正常状态
FIN-WAIT-1:等待远端发来连接终止请求,或者已经发送的连接终止请求的确认
FIN-WAIT-2:等待远端发来连接终止请求
CLOSE-WAIT:等待本地用户发来连接终止请求
CLOSING:等待远端发来连接终止请求的ack
LAST-ACK:等待之前发送到远端的连接终止请求的确认,包含远端发来连接终止请求的ack
TIME-WAIT:等待足够的时间保证远端TCP收到了它发来的连接终止请求的ack
CLOSED:此状态表示已经没有连接了
TCP连接状态的改变是事件触发的。事件包括:
1.用户调用,比如OPEN,SEND,RECEIVE,CLOSE,ABORT,STATUS
2.到来的段,尤其是包含SYN,ACK,RST和FIN标记的段
3.超时
状态转换图如下:
+---------+ ---------\ active OPEN
| CLOSED | \ -----------
+---------+<---------\ \ create TCB
| ^ \ \ snd SYN
passive OPEN | | CLOSE \ \
------------ | | ---------- \ \
create TCB | | delete TCB \ \
V | \ \
+---------+ CLOSE | \
| LISTEN | ---------- | |
+---------+ delete TCB | |
rcv SYN | | SEND | |
----------- | | ------- | V
+---------+ snd SYN,ACK / \ snd SYN +---------+
| |<----------------- ------------------>| |
| SYN | rcv SYN | SYN |
| RCVD |<-----------------------------------------------| SENT |
| | snd ACK | |
| |------------------ -------------------| |
+---------+ rcv ACK of SYN \ / rcv SYN,ACK +---------+
| -------------- | | -----------
| x | | snd ACK
| V V
| CLOSE +---------+
| ------- | ESTAB |
| snd FIN +---------+
| CLOSE | | rcv FIN
V ------- | | -------
+---------+ snd FIN / \ snd ACK +---------+
| FIN |<----------------- ------------------>| CLOSE |
| WAIT-1 |------------------ | WAIT |
+---------+ rcv FIN \ +---------+
| rcv ACK of FIN ------- | CLOSE |
| -------------- snd ACK | ------- |
V x V snd FIN V
+---------+ +---------+ +---------+
|FINWAIT-2| | CLOSING | | LAST-ACK|
+---------+ +---------+ +---------+
| rcv ACK of FIN | rcv ACK of FIN |
| rcv FIN -------------- | Timeout=2MSL -------------- |
| ------- x V ------------ x V
\ snd ACK +---------+delete TCB +---------+
------------------------>|TIME WAIT|------------------>| CLOSED |
+---------+ +---------+