一、TCP数据包的结构

TCP数据包20字节的固定首部,包括源端口、目标端口、序号、确认号、以及标志位等内容。
- 序列号seq:占4个字节,用来表示数据段的顺序,TCP把发送的所有数据字节都编上一个序号,第一个字节的编号由本地随机产生,序列号seq就是这个报文段第一个字节的数据编号。
- 确认号ack:占4个字节,表示期待收到对方下一个报文短第一个数据字节的序号,ack为收到报文最后一个字节的编号+1,即为确认号。
- 确认ACK:占一位,只有当ACK=1时,确认号字段才有效。
- 同步SYN:占一位,建立连接时用于同步序号。当SYN=1 ACK=0时表示一个请求报文段,如果同意连接,响应报文段中是的SYN=1 ACK=1 SYN标志位在TCP建立连接时才会被置1,握手完后SYN被清0。
- 终止FIN:占一位,用来释放一个连接,FIN=1表示,报文段的发送方的数据已经发送完毕,要求释放连接。 | 标志位 | 含义 | | :—-: | :—-: | | URG | 紧急指针是否有效。URG为1,需要优先处理 | | ACK | 确认号是否有效 | | PSH | 提示接收端应用立即把数据从缓冲区中读走 | | RST | 要求重新建立连接 | | SYN | 请求建立连接,并在序列号字段设置序列号初始值 | | FIN | 希望断开连接 |
二、三次握手过程

- 建立连接前:客户端处于CLOSE状态,服务器处于LISTEN状态。
- 第一次握手:客户端发送syn包到到服务器(SYN=1,syn=x),然后等待服务器确认,客户端进入SYN_SENT状态。x是客户端随机生成的数字。
- 第二次握手:服务端收到syn包后,回给客户端一个SYN+ACK包(SYN=1,ACK=1,seq=y,ack=x+1), 到到服务器进入SYN_RECV状态。
- 第三次握手:客户端收到服务器的SYN+ACK包,然后向服务器发送确认包ACK(ACK=1,syn=x+1,ack=y+1),客户端进入ESTABLISHED状态。
建立连接后:服务器收到客户端的确认后,也进入ESTABLISHED状态,双方就可以进行通信了。
三、四次挥手过程

四次挥手前:客户端处和服务端都处于ESTABLISHED状态。
- 第一次挥手:客户端发出释放连接的报文,并停止发送数据。报文首部FIN=1,序列号seq=u(u为服务端发来的数据最后一个字节的序号+1)。此时客户端进入FIN-WAIT-1(终止等待1)状态。
- 第二次挥手:服务端收到释放连接报文后,发出确认报文,ACK=1,ack=u+1,seq=v。TCP通知高层应用客户端没有数据要发了,如果服务端要发数据赶紧,此时服务端处于CLOSE-WAIT(关闭等待)状态。客户端收到服务器的确认请求后,客户端进入FIN-WAIT-2(终止等待)状态,此时客户端还要等待服务器发送的最后的数据。
- 第三次挥手:服务端数据发完以后,向客户端发送连接释放报文。服务端进入LAST-ACK(最后确认)状态,等待客户端的确认。
- 第四次挥手:客户端收到连接释放报文后,向服务端发出确认,客户端进入TIME-WAIT(时间等待)状态。此时TCP连接还未释放,经过最长报文段寿命后,如果没有继续收到服务端的数据,说明服务端连接已经关闭,客户端释放连接。
- 断开连接后:客户端处和服务端都处于CLOSED状态。
四、三次握手与四次挥手抓包
下面是在一个局域网中的两台电脑上搭建的TCP Server(IP:10.0.129.99)和 TCP Client(IP:10.0.131.68),在TCP Client上发起连接,连接成功后断开连接,使用Wireshark抓到的数据包如下。红色的为三次握手,绿色的为四次挥手,可以看到,数据包顺序及其内容与上文所诉一致。

从TCP Client向TCP Server发送一个长度为41的字符串,可以看到,数据报文中Ack为1,Len为41,响应报文的的Ack=数据报文Ack+数据报文Len
