tcp报文格式
1.端口号
标记同一台计算机上的不同进程
源端口:占2个字节,源端口和IP的作用是标记报文的返回地址。
目的端口:占2个字节,指明接收方计算机上的应用程序接口。
TCP报头中的源端口号和目的端口号同IP报头中的源IP和目的IP唯一确定一条TCP连接
2.序号
占4个字节,是TCP可靠传输的关键部分。是本报文段发送的数据组的第一个字节的序号。
在TCP传输流中,每一个字节一个序号。(例如:一个报文段的序号为300,此报文段数据部分共有100字节,则下一个报文段的序号为400.)所以序号确保了TCP传输的有序性。
3.确认序号
即ack,占4个字节,指明下一个期待收到的字节序号,表明该序号之前的所有数据已经正确无误的收到。确认号只有当ACK=1时才有效。比如建立连接时,SYN报文的ACK标志位为0。
4.数据偏移
占4位,它指出TCP报文的数据距离TCP报文段的起始处有多远。
由于首部可能含有可选项内容,因此TCP报头的长度是不确定的,报头不包含任选子段时长度为20字节;4位首部长度字段所能表示的最大值为1111,转化为10进制为15,故报头最大长度为15*32/8=60个字节。首部长度也叫数据偏移。
5.保留
为将来定义新的用途保留,一般置为0。
6.控制位
URG:紧急指针标志。1:紧急指针有效;0:忽略紧急指针。
ACK:确认序号标志。1:确认号有效;0:忽略确认号段。
PSH:push标志。1:带有push标志的数据,表示接收方在接收到该报文后应尽快将这个报文段交给应用程序,而不是缓冲区排队。
RST:重置连接标志。用于重置由于主机崩溃或其他原因而出现错误的连接。或者用于拒绝非法的报文段和拒绝连接请求。
SYN:同步序号,用于建立连接过程,在连接请求中,SYN=1和ACK=0表示该数据段没有使用捎带的确认域,而连接应答捎带一个确认,即SYN=1和ACK=1。
FIN:结束标志,用于释放连接,为1时表示发送方已经没有数据发送了,即关闭本方数据流。
7.窗口
滑动窗口大小,用来告知发送端接收端的缓存大小,以此控制发送端发送数据的速率,从而达到流量控制。窗口大小是2个字节,因而窗口大小最大为65536。
8.校验和
奇偶校验,此校验和是针对整个TCP报文段的,包括TCP报头和TCP报文数据段,以2个字节进行计算所得。由发送端计算和存储,并由接收端进行验证。
9.紧急指针
只有当URG标志置1时紧急指针才有效。紧急指针是一个正的偏移量,和顺序号字段中的值相加表示紧急数据最后一个字节的序号。TCP的紧急方式是发送端向另一端发送紧急数据的一种方式。
10.选项和填充
最常见的可选字段是最长报文大小,又称为MSS(Maximum Segment Size),每个连接方通常都在通信的第一个报文段(为建立连接而设置SYN=1的那个段)中指明这个选项,它表示本端所能接受的最大报文段的长度。选项长度不一定是32位的整数倍,所以要加填充位,即在这个字段中加入额外的0,以保证TCP头部是32的整数倍。
11.数据部分
TCP报文段中的数据部分是可选的。在一个连接建立和一个连接终止时,双方交换的报文段仅有TCP首部。如果一方没有数据要发送,也使用没有任何数据的首部来确认收到的数据。在处理超时的许多情况中,也会发送不带任何数据的报文段。
三次握手
- 第一次握手:Client将SYN置1,随机产生一个初始序列号seq发送给Server,进入SYN_SENT状态;(即 syn置1表示想要建立连接,并产生seq)
- 第二次握手:Server收到Client的SYN=1之后,知道客户端请求建立连接,将自己的SYN置1,ACK置1,产生一个acknowledge number=sequence number+1,并随机产生一个自己的初始序列号,发送给客户端;进入SYN_RCVD状态;(即 同样将syn置1表示想要建立连接,并产生seq,ack置为1表示收到了 并产生ack num 为收到的seq+1)
- 第三次握手:客户端检查acknowledge number是否为序列号+1,ACK是否为1,检查正确之后将自己的ACK置为1,产生一个acknowledge number=服务器发的序列号+1,发送给服务器;进入ESTABLISHED状态;服务器检查ACK为1和acknowledge number为序列号+1之后,也进入ESTABLISHED状态;完成三次握手,连接建立。(客户端检查返回的ack是否为1,检查后将自己的ack变成1,表示自己收到了,并产生ack num为服务器的seq+1 现在)
能否两次握手?
1.可能会出现已失效的连接请求报文段又传到了服务器端。建立连接以后,第一次的syn包又发了过去,然后服务器端认为建立连接,就等待接收资源,而客户端并没有收到信息建立连接,在客户端看只有第二次连接成功,服务器则显示建立两次连接,浪费服务器资源。
2.两次握手无法保证Client正确接收第二次握手的报文(Server无法确认Client是否收到)
能否四次握手?
可以 但没必要。
三次握手中服务器的ack和syn分开发 多通信一次。四次握手中二三次合并为三次握手。
四次挥手
- 第一次挥手:Client将FIN置为1,发送一个序列号seq给Server;进入FIN_WAIT_1状态;
- 第二次挥手:Server收到FIN之后,发送一个ACK=1,acknowledge number=收到的序列号+1;进入CLOSE_WAIT状态。此时客户端已经没有要发送的数据了,但仍可以接受服务器发来的数据。
- 第三次挥手:Server将FIN置1,发送一个序列号给Client;进入LAST_ACK状态;
- 第四次挥手:Client收到服务器的FIN后,进入TIME_WAIT状态;接着将ACK置1,发送一个acknowledge number=序列号+1给服务器;服务器收到后,确认acknowledge number后,变为CLOSED状态,不再向客户端发送数据。客户端等待2*MSL(报文段最长寿命)时间后,也进入CLOSED状态。完成四次挥手。
首先,客户端想和服务器端断开,发送fin包,服务端收到了,返回一个ack,此时服务端是 CLOSE_WAIT。然后服务器端想和客户端断开,发送fin包,客户端收到后TIME_WAIT状态,然后客户端返回ack ,服务器收到后,变为CLOSED状态,客户端等待2*MSL(报文段最长寿命)时间后,也进入CLOSED状态。