关于TCP的三次握手建立连接和四次挥手断开连接

一、整理文章起因

工作中一次和其他业务对接接口,在使用过程中出现了我这边请求对方接口,而对方说没有收到我的请求,并且该现象还在持续发生,于是我通过tcpdump进行抓包分析,抓包结果如下:

 

 

 这次的抓包和标准的四次挥手断开连接有点区别,想着很多时候现在面试一般都会问这些基础的协议相关内容,三次握手四次断开连接,TCP,UDP等,所以也想通过这次复习,把很多遗漏地方补充一下

 

二、TCP报文格式

 

对上图重要字段说明:

Source Port: 源端口,16位

Destination Port:目的端口16位

Sequence Number:序列号,32位

Acknowledgment Number:确认序号,32位

 

Control Bits:

URG:  紧急指针有效

ACK:  确认序号有效

PSH:  Push Function

RST:  复位TCP连接

SYN:  发起一个新连接

FIN:  没有更多的数据发送 ,释放一个tcp连接

 

注意:不要把确认序号和标志位中的ACK弄混了,Ack确认号是对发起方的Seq+1 

 

关于TCP连接过程中不同连接状态的说明:

  1. LISTEN:侦听来自远方的TCP端口的连接请求. 
  2. SYN-SENT:在发送连接请求后等待匹配的连接请求
  3. SYN-RECEIVED:在收到和发送一个连接请求后等待对方对连接请求的确认
  4. ESTABLISHED:代表一个打开的连接,可以接收数据
  5. FIN-WAIT-1:等待远程TCP连接中断请求,或先前的连接中断请求的确认
  6. FIN-WAIT-2:从远程TCP等待连接中断请求
  7. CLOSE-WAIT:等待从本地用户发来的连接中断请求
  8. CLOSING:等待远程TCP对连接中断的确认
  9. LAST-ACK:等待原来的发向远程TCP的连接中断请求的确认
  10. TIME-WAIT:等待足够的时间以确保远程TCP接收到连接中断请求的确认 
  11. CLOSED:没有任何连接状态

 

 

为了方便理解,写一个一个socket服务端和客户端,抓包分析内容,来看一个标准的tcp三次握手和四次挥手

服务端代码:

import socket,os



server = socket.socket()
server.bind(('0.0.0.0',6666))
server.listen()


while True:
     conn,addr = server.accept()
     print("一个新的连接:",addr)
     try:
          while True:
               print("等待接收")
               data = conn.recv(1024)
               if not data:
                  break
               print("recv data:",data)
               res = data.decode("utf-8").upper()
               conn.send(res.encode())
               print("send done")
     except Exception as e:
           print(e)
          
server.close()

客户端代码:

import socket,os

client = socket.socket()

client.connect(('192.168.188.106', 6666))

while True:
    cmd = input(">>:").strip()
    client.send(cmd.encode("utf-8"))
    cmd_res = client.recv(1024)
    print(cmd_res.decode())
client.close()

抓包对客户端和服务端的的通信过程进行分析,这是一个非常的标准的三次握手和四次挥手过程:

 

 先看针对上图中的三次握手:

 在看看四次挥手的整理

 

 

 

 

 

 

 

 关于TCP断开连接的说明

从上面的图我们可以看到是客户端主动断开连接,那么我们站在客户端的服务端两方面

对于客户端来说:

  1. 发送FIN告诉服务端要关闭连接,并自己进入FIN-WAIT-1状态,这个时候就不再处理和发送应用层用户的数据
  2. 收到服务端对FIN的ACK后,客户端进入FIN-WAIT-2状态,这个时候依然可以接收服务端的数据,如果收不到对方的ACK会再次发送之前包含FIN在内的消息
  3. 收到服务端发送的FIN之后说明服务端也没有数据发送并关闭连接了,此时客户端发送ACK对服务端的FIN进行确认并进入TIME-WAIT,然后等待2MS连接关

对于服务端来说:

  1. 收到客户端发送的FIN,发送ACK对这个FIN消息进行确认,并进入到CLOSE-WAIT状态
  2. 服务单在发送FIN的之前,如果还有未发送的数据,可以继续发送,发送FIN之后进入LAST-ACK
  3. 等待客户端的ACK消息确认自己的FIN完成关闭,如果客户端没有确认会再次发送FIN

 

 

小结:

发送FIN之后的一端将不会再发送数据

被断开的一方收到FIN后,给对方发送ACK表示收到,并自己的状态更改为CLOS-WAIT,此时TCP连接处于半关闭状态。被断开的一方仍然可以发送数据

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章