TCP的三次握手
1、概述
TCP三次握手是浏览器和服务器建立连接的方式,目的是为了使二者能够建立连接,便于后续的数据交互传输。
第一次握手:浏览器向服务器发起建立连接的请求。
第二次握手:服务器告诉浏览器,我同意你的连接请求,同时我也向你发起建立连接的请求。
第三次握手:浏览器也告诉服务器,我同意建立连接。
至此,双方都知道对方同意建立连接,并准备好了进行数据传输。
2、具体过程
参数说明
SYN:
- TCP报文中的标志位字段之一。
- 在建立连接时使用,用来同步序号。
- 当 SYN=1,ACK=0 时,表示这是一个请求建立连接的报文段。
- 当 SYN=1,ACK=1 时,表示对方同意建立连接。
- SYN=1 时,说明这是一个请求建立连接或同意建立连接的报文。只有在前两次握手中 SYN 才为 1。
ACK:
-
TCP报文中的标志位字段之一。
-
表示前面的确认号字段是否有效,ACK=1 时表示有效。只有当 ACK=1 时,前面的确认号字段才有效。
-
TCP 规定,连接建立后,ACK 必须为 1。
seq:
- TCP报文中的序列号字段。
- 占32位(bit),表示本报文段所发送数据的第一个字节的编号。在TCP连接中,所传送的字节流的每一个字节都会按顺序编号。
ack:
- TCP报文中的确认号字段。
- 占32位(bit),表示接收方期望收到发送方下一个报文段的第一个字节数据的编号。
0、初始状态
服务端监听某个端口,处于 LISTEN 状态。
1、客户端发送TCP连接请求
客户端会随机一个初始序列号seq=x(client_isn),设置SYN=1 ,表示这是SYN握手报文。
然后就可以把这个 SYN 报文发送给服务端了,表示向服务端发起连接,之后客户端处于 同步已发送状态。
2、服务端发送针对TCP连接请求的确认
服务端收到客户端的 SYN 报文后,也随机一个初始序列号seq=y(server_isn)
设置ack=x+1,表示收到了客户端的x之前的数据,希望客户端下次发送的数据从x+1开始。
设置 SYN=1 和 ACK=1。表示这是一个SYN握手和ACK确认应答报文。
最后把该报文发给客户端,该报文也不包含应用层数据,之后服务端处于同步已接收状态。
3、客户端发送确认的确认
客户端收到服务端报文后,还要向服务端回应最后一个应答报文。
将ACK置为 1 ,表示这是一个应答报文。
设置ack=y+1 ,表示收到了服务器的y之前的数据,希望服务器下次发送的数据从y+1开始。
最后把报文发送给服务端,这次报文可以携带数据,之后客户端处于连接已建立状态。
服务器收到客户端的应答报文后,也进入连接已建立状态。
3、为什么是三次握手?
3.1、主要原因是为了防止历史连接。
三次握手的时候,如果网络拥堵,第一次握手的SYN包没能到达服务端,那么客户端就会连续发送多次SYN建立连接的报文,那就有可能出现一个【后发送的SYN报文】比一个【早发送的SYN报文】早到达服务端。
那么此时服务端就会回一个 SYN + ACK 报文给客户端;
- 如果是两次握手连接,就不能判断当前的连接是否是历史连接,导致错误。
- 如果是三次握手连接,客户端收到后可以根据自身的上下文,判断这是一个历史连接(序列号过期或超时),那么客户端就会发送 RST 报文给服务端,中止这一次连接。
3.2、三次握手可以避免资源浪费
如果只有两次握手,当客户端的 SYN 请求连接在网络中阻塞,客户端没有接收到 ACK 报文,就会重新发送 SYN。
如果是三次握手,第三次握手时服务器可以得到客户端的ack,知道连接已成功建立。
如果没有第三次握手,服务器不清楚客户端是否收到了自己发送的建立连接的 ACK 确认信号,所以每收到一个 SYN 就只能先主动建立一个连接。
如果客户端的 SYN 阻塞了,重复发送多次 SYN 报文,那么服务器在收到请求后就会建立多个冗余的无效链接,造成不必要的资源浪费。
学习参考: