在互联网通信中,确保数据传输的可靠性至关重要。TCP三次握手的过程正是为了解决这一问题而设计的。在建立连接之前,客户端和服务器需要确认彼此的存在与准备状态,以防止因网络延迟或数据丢失而导致的错误。通过三次握手,双方不仅能够同步序列号,还能有效地建立稳定的通信链路,从而保证后续数据传输的顺利进行。
TCP基础认识
让我们一起来探索一下TCP头部的格式吧。其中,用颜色标注的部分是与我们讨论的主题关系比较密切的字段,而其余部分我们就暂时不深入探讨了。
序列号:在建立连接的过程中,由计算机生成的一个随机数值被用作初始序列号,并通过SYN数据包传递给接收端主机。每当发送数据时,该序列号会根据所发送的数据字节数进行相应的递增。这种方法有助于解决网络传输中可能出现的数据包乱序问题。
确认应答号:下次预期接收的数据序列号,即为确认应答(ACK)中所指的序列号。当发送端接收到此确认应答后,可以认为该序列号之前的所有数据均已成功传输至接收端。这一机制主要用于解决网络传输过程中可能出现的数据包丢失问题。
控制位:
ACK
:当这个位是1
的时候,「确认应答」就生效了。TCP 规定,除了刚开始建立连接时发送的 SYN 包之外,其他情况下这个位都必须设为1
。
RST
:当这个位是1
的时候,意味着 TCP 连接出了问题,必须强制断开。
SYN
:当这个位置是1
的时候,就表示想要建立连接,并且会在[序列号]那一栏设定一个起始的序列号。
FIN
:当这个位置为1
时,意味着之后不会再发送数据了,想要结束连接。当双方都完成了通信并且想要断开连接时,两台电脑会互相发送FIN
位设为1
的TCP数据包。
TCP连接建立
TCP
是一种需要先建立连接才能使用的协议。在开始传输数据之前,双方得通过一个叫做“三次握手”的过程来建立起这个连接。具体怎么握手的步骤可以看下面的图。
TCP三次握手过程
一开始,客户端和服务端都处于CLOSED
状态。先是服务端主动监听某个端口,处于LISTEN
状态。
第一个报文:SYN报文
客户端会随机初始化序号
client_isn
,将此序号置于TCP
首部的序号字段中,同时把SYN
标志位置为1
,表示SYN
报文。接着把第一个SYN
报文发送给服务端,表示向服务端发起连接,该报文不包含应用层数据,之后客户端处于SYN-SENT
状态。
第二个报文:SYN+ACK报文
服务端收到客户端的
SYN
报文后,首先服务端也随机初始化自己的序号server_isn
,将此序号填入TCP
首部的序号字段中,其次把TCP
首部的确认应答号字段填入client_isn+1
, 接着把SYN
和ACK
标志位置为1
。最后把该报文发给客户端,该报文也不包含应用层数据,之后服务端处于SYN-RCVD
状态。
第三个报文:ACK报文
- 客户端收到服务端报文后,还要向服务端回应最后一个应答报文,首先该应答报文
TCP
首部ACK
标志位置为1
,其次确认应答号字段填入server_isn+1
,最后把报文发送给服务端,这次报文可以携带客户到服务器的数据,之后客户端处于ESTABLISHED
状态。- 服务器收到客户端的应答报文后,也进入
ESTABLISHED
状态。
通过ENSP搭建一个简单的实验环境,如下图
为了让大家直观了解三次握手的过程,以下通过Wireshark
抓包软件,抓取三次握手的数据包。
- 第一次握手标志位
从标志位看出,同步位有值,在做请求SYN
:Syn
同步位为1
- 第二次握手标志位
从标志位看出,确认位、同步位有值,在做应答SYN+ACK
:Syn
同步位为1
、Acknowledgment
确认位为1
。
- 第三次握手标志位
从标志位看出,只有确认位有值,在做再次确认SYN
:Acknowledgment
确认位为1
常见面试题
- TCP 建立连接为什么要三次握手而不是两次?
TCP连接需要三次握手,而不是两次,主要是为了保证两边都能顺利通信,而且连接稳定。第一次握手时,客户端告诉服务器想建立连接;第二次握手,服务器回复说它已经准备好接受连接了;第三次握手是客户端再次确认,确保双方都已经准备好发送数据了。如果只有两次握手的话,有时候可能会导致客户端和服务器之间的情况不对等,造成数据丢失或者连接不稳定的问题。所以,通过三次握手,可以确保两边都确认好了,为后面的数据传输做好准备。
- TCP 建立连接为什么要三次握手而不是四次?
TCP用三次握手而不是四次来建立连接,是因为三次已经足够确认双方状态和同步序列号了。第一次握手是客户端发出请求,第二次握手是服务器回应,第三次握手是客户端再次确认,这样就能可靠地建立起连接。如果改成四次握手,反而会增加不必要的等待时间和资源浪费。三次握手既能保证双方都准备好通信,又能快速有效地完成连接。
- 有一种网络攻击是利用了TCP建立连接机制的漏洞,你了解吗?这个问题怎么解决?
一种利用TCP连接建立过程中潜在安全漏洞的网络攻击手段被称为TCP SYN Flood攻击。此类攻击策略性地利用了TCP三次握手协议的特性,通过向目标服务器发送大量SYN(同步序列编号)请求报文,但故意不响应最终的ACK(确认应答)报文来完成握手过程。这种行为会导致目标服务器上开放大量的半开连接状态,进而消耗其有限的资源,如内存和处理能力,最终使得服务器难以或无法为合法用户提供服务。
解决方案:
- SYN Cookies:服务器在收到SYN请求时不立即分配资源,而是生成一个加密的SYN Cookie,只有在收到合法的ACK时才会真正建立连接。
- 限制SYN请求速率:通过配置防火墙或入侵检测系统(IDS)来限制某个IP地址的SYN请求频率,防止过多请求。
- 使用负载均衡:将流量分散到多个服务器,减少单一服务器的压力。
- 设置连接超时:调整服务器的连接超时设置,减少等待状态的持续时间。
推荐阅读
-
Linux命令记不住?试试这个神奇的工具,让你事半功倍!
-
AWK不再难:案例驱动学习,让你成为数据处理高手
-
忘记密码?一招教你轻松重设欧拉系统密码!
-
从监控到优化:掌握磁盘I/O性能工具的使用
-
超越top!探索htop在Linux系统监控中的超强功能
-
网络架构大解析:这五种拓扑结构将改变你对网络的认知!
-
掌握Linux性能监控神器:atop实用指南
-
告别繁琐操作,掌握一线工作中的Shell脚本绝招!
-
重磅消息:utools工具插件现在完全免费,快来享受!
-
不可错过!字节跳动打造的最新生产力工具来了
-
提升效率必备!学习awk命令,轻松搞定数据
-
高效传输秘籍,揭秘Rsync和SCP的优劣,助你做出明智选择!
-
当你拥有一台云服务器,你最想做的事情是啥?
-
IP地址乱成一团?用Shell一键搞定!
-
Nginx日志分析:编写Shell脚本进行全面日志统计
-
如何用find命令按文件大小快速查找并美化输出显示
-
不再担心数据丢失:用rsync打造你的自动化备份解决方案
-
从繁琐到简单:Python实现快速批量文件重命名攻略!