TCP协议的三次握手和四次挥手

本文详细解析TCP协议的三次握手建立连接过程及四次挥手断开连接过程,探讨了SYN洪水攻击及其解决方案,以及TIME_WAIT状态的处理方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于三次握手图解

在这里插入图片描述
如图,三次握手中Client发送端,Server为接收端

建立连接前需要Server端先监听端口,因此Server建立连接前的初始状态就是LISTEN状态,

  1. Client端准备建立连接,先发送一个SYN同步包,发送完同步包后Client端的状态就变成了SYN_SENT,

  2. Server收到SYN后同意建立连接会向Client端回复一个ACK,由于TCP是双工传输,Server端也会同时像Client端发送一个同步请求SYN申请Server向Client方向建立连接,发送完ACK和SYN后Server端的连接状态就变成了SYN_RCVD,

  3. Client收到Server的ACK后,Client端的连接状态就变成了ESTABLISHED,同时Client端向Server端发送ACK响应,回复Server端的SYN请求,Server端收到Client端的ACK后,Server端的连接状态就变成ESTABLISHED状态,

此时建联完成。

三次握手是为了建立双向的连接
建联中可能出现SYN洪水攻击,其产生的原因以及解决方案。
SYN洪水攻击发生的原因:就是Server端收到Client端的SYN请求后,发送了ACK和SYN,但是Client端不进行回复,导致Server端大量的连接出现在SYN_RCVD状态,进而影响其他请求的建联,
解决方案:可以通过设置TCP的参数(修改重试次数)SYN_retries=0加快半连接的回收速度,或者(修改等待数)syn_backlog=2048调大MAC来应对少量的SYN洪水攻击。

关于四次挥手图解

在这里插入图片描述
如图,四次挥手中Client发送端,Server为接收端

断连四次挥手,通信双方都可以发起,这里举例Client先发起

  1. Client向Server发起了一个FIN包表示Client端已经没有数据要发送,然后Client端就进入FIN_WAIT_1状态,
  2. Server端收到FIN后返回ACK然后进入CLOSE_WAIT状态,此时Server属于半关闭状态,因为此时Client向Server方向已经不会再发送数据了,可是Server向Client端可能还有数据要发送,
  3. 当Server端数据发送完毕后Server端向Client端发送FIN表示Server端也没有数据要发送,这是Server进入LAST_ACK状态,就等待Client端的应答就关闭连接了,
  4. Client端收到Server端的FIN后回复ACK然后进入TIME_WAIT状态,TIME_WAIT状态下需要等待2MSL就是最大报文段生存时间(一个IP数据包能在互联网上生存的最长时间)来保证连接的可靠关闭,之后才会进入CLOSED状态,而Server端收到ACK后直接进入CLOSED状态。

为什么要等待两倍的MSL才关闭连接?
原因:
1.要保证TCP协议的全双工连接能够可靠关闭
2.保证这次连接中重复的数据段能够从网络中消失,防止端口被重用的时候可能会产生数据混淆。

在断联的时候可能会出现大量的socket出现在TIME_WAIT或者CLOSE_WAIT状态的问题

解决方案:一般开启TCP参数在 /etc/sysctl.conf中加入
net.ipv4.tcp_tw_recycle = 1 (表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭)加快TIME_WAIT状态的回收。
而出现大量CLOSE_WAIT状态一般是被动关闭的一方可能出现代码的bug,没有正确关闭连接导致的

总结:
从这个交互流程中可以看出不论是建联还是断联,都是需要在两个方向上进行,只不过建联时Server端的SYN和ACK合并为一次发送,而断开连接是两个数据停止时间可能是不同的,所以无法合并FIN和ACK发送,这就是建联的时候必须要三次握手而断联的时候必须要四次挥手的原因。

### TCP协议三次握手四次挥手详解 #### 三次握手过程 TCP协议通过三次握手立可靠的连接。以下是三次握手的具体过程: 1. 客户端向服务器发送一个SYN(同步)报文段,表示请求立连接,并随机生成一个初始序列号`Seq = x`[^1]。 2. 服务器收到客户端的SYN报文后,返回一个SYN+ACK报文段。该报文段包含两个信息:一是确认客户端的SYN报文,二是服务器也随机生成一个初始序列号`Seq = y`,同时将确认号设置为`Ack = x + 1`[^1]。 3. 客户端收到服务器的SYN+ACK报文后,发送最后一个ACK(确认)报文段,将确认号设置为`Ack = y + 1`。此时,客户端服务器都认为连接已成功立。 通过三次握手,可以确保双方都准备好进行数据传输,并解决可能存在的丢包问题[^2]。 #### 四次挥手过程 TCP协议通过四次挥手开连接,以确保所有数据能够完全传输。以下是四次挥手的具体过程: 1. 主动关闭方(通常是客户端)发送一个FIN(结束)报文段,表示不再发送数据,但仍然可以接收数据,同时设置序列号`Seq = u`。 2. 被动关闭方(通常是服务器)收到FIN报文后,返回一个ACK(确认)报文段,将确认号设置为`Ack = u + 1`,表示已经接收到关闭请求。 3. 被动关闭方完成未完成的数据传输后,发送一个FIN报文段,表示自己也不再发送数据,同时设置序列号`Seq = v`[^1]。 4. 主动关闭方收到FIN报文后,返回一个ACK(确认)报文段,将确认号设置为`Ack = v + 1`。此时,双方都认为连接已成功开[^1]。 由于TCP协议需要确保数据完全传输,因此在开连接时需要额外的一次握手来确认被动关闭方的数据传输完成情况。 #### 示例代码 以下是一个简单的Python代码示例,展示如何使用`socket`模块模拟TCP连接的立与开: ```python import socket # 创一个TCP/IP套接字 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 连接到服务器(模拟三次握手) server_address = ('localhost', 10000) sock.connect(server_address) try: # 发送数据 message = 'This is the message. It will be repeated.' sock.sendall(message.encode()) # 查看响应 data = sock.recv(1024) print('Received:', data.decode()) finally: # 关闭连接(模拟四次挥手) sock.close() ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值