TCP 的三次握手和四次挥手过程是什么?为什么要这么设计?

TCP连接建立时需要进行三次握手,关闭时需要四次挥手。这是为了确保连接的可靠性。

三次握手过程:

  1. 客户端发送SYN数据包到服务器,并进入SYN_SENT状态,等待响应。
  2. 服务器接收到SYN数据包,发回SYN+ACK数据包,并进入SYN_RCVD状态。
  3. 客户端收到SYN+ACK数据包,发回ACK数据包,并进入ESTABLISHED状态。服务器收到ACK,也进入ESTABLISHED状态。

三次握手的目的是:

  1. 服务器确认客户端的地址和端口正确无误;
  2. 客户端确认服务器收到SYN请求,并且服务器的地址和端口也正确;
  3. 确保双方都进入ESTABLISHED状态,之后再开始传输数据。
    这可以防止已失效的连接请求报文段突然又传送到服务器,将其错误地提交给一个新创建的连接。

四次挥手过程:

  1. 客户端进入FIN_WAIT_1状态,发送FIN数据包表示没有数据要发送。
  2. 服务器收到FIN,进入CLOSE_WAIT状态。发送ACK确认,并继续接收数据。
  3. 服务器待接收完所有数据后,也发送FIN进入LAST_ACK状态。
  4. 客户端收到FIN,发ACK进入TIME_WAIT状态。等待2MSL后返回CLOSED状态。
    服务器收到ACK后也进入CLOSED状态。

四次挥手的目的:

  1. 允许客户端和服务器交换任意速率的FIN;
  2. 服务器可以完整接收所有在连接中发送的数据;
  3. 客户端等待超时并重新发送FIN,以防止误判已丢弃的报文段;
  4. 确保双方都进入CLOSED状态,释放资源。

代码示例:
TCP客户端:

python
import socket   

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
sock.connect(('127.0.0.1', 8888))

# 发送SYN进行三次握手  
sock.send(b'SYN')   

data = sock.recv(100)   # 收到SYN+ACK
sock.send(b'ACK')      # 发送ACK完成三次握手

# 发送FIN进行四次挥手
sock.send(b'FIN')
data = sock.recv(100)   # 收到ACK 
sock.close()            # 等待2MSL后关闭

TCP服务器:

python
import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
sock.bind(('127.0.0.1', 8888))  
sock.listen(5)  

conn, addr = sock.accept()  

data = conn.recv(100)    # 收到SYN
conn.send(b'SYN+ACK')   # 发送SYN+ACK

data = conn.recv(100)    # 收到ACK完成三次握手  

data = conn.recv(100)  # 收到FIN   
conn.send(b'ACK')      # 发送ACK  

conn.send(b'FIN')      # 发送自己的FIN
data = conn.recv(100)   # 收到ACK  

conn.close()            # 关闭连接  

总之,TCP的三次握手和四次挥手过程可以确保连接的可靠建立和可靠释放,是TCP/IP协议中非常重要的机制。理解TCP连接的建立和释放过程,有助于我们设计和实现网络应用程序。