TCP三次握手和四次挥手(详细+通俗)

TCP/IP协议中,TCP的三次握手和四次挥手机制

看了一些资料和讲解视频,整理下。
上部分是比较详细的讲解,“详尽”,
下部分是比较通俗的讲解,“通俗”。
想怎么回答这个问题,废话不说了,全文背诵(其实是一定要理解才行)

一.详尽
在这里插入图片描述
首先在TCP报文格式中,有六大标志位 :
在这里插入图片描述

    SYN,同步标志位;ACK 确认标志位;PSH 传送标志位;
    FIN 结束标志位;RST 重置标志位;URG 紧急标志位;

还有seq 序号;ack 确认号

1.三次握手:
准备工作:服务器必须准备好接受外来的连接。这通常通过调用socket,bind和listen这三个函数来完成。我们称之为被动打开。
服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。
TCP是全双工通信,任何一方都可以发起建立连接的请求,假设A是客户端,B是服务器。
初始时A和B均处于CLOSED状态,B会创建传输进程控制块TCB,然后处于LISTEND状态,监听端口是否收到了TCP请求以便及时响应。
在这时如果有个客户端初始化一个Socket,然后调用(connect)连接服务器

第一次握手:建立连接。客户端发送连接请求报文段,将 SYN 位置为 1,Sequence Number 为 x;然后,客户端进入 SYN_SEND 状态,等待服务器的确认;
2)
第二次握手:服务器收到 SYN 报文段。服务器收到客户端的 SYN 报文段,需要对这个 SYN 报文段进行确认,设置 Acknowledgment Number 为x+1(Sequence Number+1);同时,自己自己还要发送 SYN 请求信息,将 SYN 位置为 1,Sequence Number 为y;服务器端将上述所有信息放到一个报文段(即 SYN+ACK 报文段)中,一并发送给客户端,此时服务器进入 SYN_RECV 状态;
3)
第三次握手:客户端收到服务器的 SYN+ACK 报文段。然后将 Acknowledgment Number设置为 y+1,向服务器发送 ACK 报文段,这个报文段发送完毕以后,客户端和服务器端都进入 ESTABLISHED 状态,完成 TCP 三次握手。

2.四次分手呢?
当客户端和服务器通过三次握手建立了 TCP 连接以后,当数据传送完毕,肯定是要断开 TCP 连接的啊。那对于 TCP 的断开连接,这里就有了神秘的“四次分手”。
1)
第一次分手:主机 1(可以使客户端,也可以是服务器端),设置 Sequence Number和 Acknowledgment Number,向主机 2 发送一个 FIN 报文段;此时,主机 1 进入 FIN_WAIT_1 状态;这表示主机 1 没有数据要发送给主机 2 了;
2)
第二次分手:主机 2 收到了主机 1 发送的 FIN 报文段,向主机 1 回一个 ACK 报文段,Acknowledgment Number 为 Sequence Number 加 1;主机 1 进入 FIN_WAIT_2 状态;主机 2 告诉主机 1,我“同意”你的关闭请求;
3)
第三次分手:主机 2 向主机 1 发送 FIN 报文段,请求关闭连接,同时主机 2 进入 LAST_ACK 状态;
4)
第四次分手:主机 1 收到主机 2 发送的 FIN 报文段,向主机 2 发送 ACK 报文段,然后主机 1 进入 TIME_WAIT 状态;主机 2 收到主机 1 的 ACK 报文段以后,就关闭连接;此时,主机 1 等待 2MSL 后依然没有收到回复,则证明 Server 端已正常关闭,那好,主机 1 也可以关闭连接了。

3.TCP 为啥挥手要比握手多一次?
(1)因为当处于 LISTEN 状态的服务器端收到来自客户端的 SYN 报文(客户端希望新建一个TCP 连接)时,它可以把 ACK(确认应答)和 SYN(同步序号)放在同一个报文里来发送给客户端。
(2)但在关闭 TCP 连接时,当收到对方的 FIN 报文时,对方仅仅表示对方已经没有数据发送给你了,但是你自己可能还有数据需要发送给对方,则等你发送完剩余的数据给对方之后,再发送 FIN 报文给对方来表示你数据已经发送完毕,并请求关闭连接,所以通常情况下,这里的 ACK 报文和 FIN 报文都是分开发送的。

4.为什么一定进行三次握手?
当客户端向服务器端发送一个连接请求时,由于某种原因长时间驻留在网络节点中,无法达到服务器端,由于 TCP 的超时重传机制,当客户端在特定的时间内没有收到服务器端的确认应答信息,则会重新向服务器端发送连接请求,且该连接请求得到服务器端的响应并正常建立连接,进而传输数据,当数据传输完毕,并释放了此次 TCP 连接。
若此时第一次发送的连接请求报文段延迟了一段时间后,到达了服务器端,本来这是一个早已失效的报文段,但是服务器端收到该连接请求后误以为客户端又发出了一次新的连接请求,于是服务器端向客户端发出确认应答报文段,并同意建立连接。
如果没有采用三次握手建立连接,由于服务器端发送了确认应答信息,则表示新的连接已成功建立,但是客户端此时并没有向服务器端发出任何连接请求,因此客户端忽略服务器端的确认应答报文,更不会向服务器端传输数据。而服务器端却认为新的连接已经建立了,并在一直等待客户端发送数据,这样服务器端一直处于等待接收数据,直到超出计数器的设定值,则认为服务器端出现异常,并且关闭这个连接。
在这个等待的过程中,浪费服务器的资源。如果采用三次握手,客户端就不会向服务器发出确认应答消息,服务器端由于没有收到客户端的确认应答信息,从而判定客户端并没有请求建立连接,从而不建立该连接。

*二.通俗

1.三次握手:
TCP/IP协议是传输层的一个面向连接的安全可靠的传输协议,三次握手的机制是为了在客户端和服务端建立一个安全可靠的连接。

   客户端:你在线吗?
   服务器:我在,你在线吗?
   客户端:我在

(1)首先客户端想要连接服务器进行通信,这时由客户端发起第一次握手,客户端会向服务端发送一个报文,在这个报文中:SYN标志位置为1,表示发起新的连接,还有一个32位随机序列号seq.
(2)于是服务器在收到这个报文之后,就知道了这个客户端想要和我建立新的连接,于是服务器端就向客户端发送一个确认消息包。在这个消息包里:一个SYN表示新的连接请求,ACK标志位置为1,表示确认客户端发起的第一次连接请求,一个新的32位序列号seq,以及32位消息确认序号为第一次握手中seq+1;
(3)那么两次握手之后,对于客户端而言:已经明确了我既能给服务端成功发送消息,也能成功收到服务端的响应。但是对于服务器而言,两次握手是不够的,因为到目前为止,服务端只知道客户端发给我的消息我能收到这一件事,对于我给客户端发送的消息客户端能不能收到,我是不知道的。所以还要进行三次握手。
(4)第三次握手就是当客户端收到服务端发送的确认响应报文后,还要继续去给服务端进行响应,也就是一个ack标志位置1的确认消息。
通过以上三次,不管是客户端还是服务端,都知道我能给对方发送消息,也能收到对方的响应,那么,这个连接就被安全的建立了。(全双工)

2.为什么不进行四次握手?
其实理论上是可以的,就是在服务端收到客户端第一次连接请求之后,第二次握手发送给客户端确认消息的时候,可以把ACK和SYN分两次发送,但是太浪费资源了,一次能干完的事情为什么要分为两次呢?

3. 四次挥手

   客户端:我数据传完了,我要下线了
   服务器:知道了,我还有点数据,你等下
   一段时间后:
   服务器:我数据发完了,你可以下线了
   客户端:好的

首先是客户端发送给服务端的,请求报文为FIN值为1的,也就是告诉服务器说,我要断开了,此时,服务器接受到消息,就知道客户端想要和我断开,会立刻返回一个确认报文ACK为1的给客户端,因为此时服务器可能还有一些信息没有处理完成,就说,你等等,然后稍等片刻会给客户端发送一个消息,就说我这边消息已经发完了,你可以断开了,但是此时服务器不知道客户端是否能够收到消息,所以说最后客户端会返回一个确认报文ACK值为1的报文,这样服务端才知道客户端是收到了同意分手的消息的,只有这样才能保证连接的安全性,少一次都不行。
4.为啥不是三次挥手?
因为客户端要关闭连接的时候,无法保证服务器已经将数据发送完成,所以此时服务器只能告诉客户端我收到你的断开请求,直到你的数据发送完成。在服务器把数据发送完成之后,告知客户端,数据发送完了,可以关闭连接了。此时,客户端也要应答,同意关闭连接
如果客户端不确认呢?反正两边已经发完数据了,最后一次挥手没有会怎么样呢?
客户端的确认是为了让服务端知道服务端的FIN确实到达了,否则服务端就会一直怀疑自己的FIN丢了(会发生超时重传)

5.为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可能最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。

6.如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

状态转移图
在这里插入图片描述
CLOSED:起始点,不在连接状态。可以主动打开连接,或者等待对端的连接。

–>收到“被动打开”报文,进入LISTEN状态。

–>收到“主动打开”报文,进入SYN_SENT状态。

–>收到任何报文段,发送RST报文段。

–>收到其它任何报文段,发出差错报文。

LISTEN:被动打开,TCP正在等待对端的连接请求。

–>收到“发送数据”报文,发送SYN报文段,进入SYN_SENT状态。

–>收到任何SYN报文段,发送SYN+ACK报文段,进入SYN_RECEIVED状态。

–>收到任何其它报文段或者报文,发送差错报文。

SYN_SENT:主动打开,发送完一个连接请求后等待回复。

–>超时,进入CLOSED状态。

–>收到SYN报文段,发送SYN+ACK报文段,进入SYN_RECEIVED状态。

–>收到SYN+ACK报文段,发送ACK报文段,进入ESTABLISHED状态。

–>收到任何其它报文段或者报文,发送差错报文。

SYN_RECEIVED:被动打开,接受连接请求以后进行确认同时也向对端发送连接请求发送,等待对方的回复。

–>超时,发送RST报文段,进入CLOSED状态。

–>收到ACK报文段,进入ESTABLISHED状态。

–>收到"关闭"报文,发送FIN报文段,进入FIN_WAIT_1状态。

–>收到RST报文段,进入LISTEN状态。

–>收到任何其它报文段或者报文,发送差错报文。

ESTABLISHED:三次握手完毕,TCP连接建立完成,可以传输数据。

–>收到FIN报文段,进入CLOSED_WAIT状态。

–>收到“关闭”报文,发送FIN报文段,进入FIN_WAIT_1状态。

–>收到RST或SYN报文段,发出差错报文。

–>收到数据或ACK报文段,调用输入模块。

–>收到“发送”报文,调用输出模块。

FIN_WAIT_1:四次挥手开始,主动关闭,发送断开连接请求,等待对端确认。

–>收到FIN报文段,发送ACK报文段,进入CLOSING状态(同时关闭)。

–>收到FIN+ACK报文段,发送ACK报文段,进入FIN_WAIT状态(?)。

–>收到ACK报文段,进入FIN_WAIT_2状态。

–>收到任何其它报文段或者报文,发送差错报文。

FIN_WAIT_2:接收对方确认,但未接受对方的断开连接请求。

–>收到FIN报文段,发送ACK报文段,进入TIME_WAIT状态。

CLOSING:主动关闭的一方本希望收到对方的ACK却收到了对方的断开连接请求。

–>收到ACK报文段,进入TIME_WAIT状态。

–>收到任何其它报文段或者报文,发送差错报文。

TIME_WAIT:对方确认后发起断开连接请求,需要等待2MSL保证正常关闭。

–>超时,进入CLOSED状态。

–>收到任何其它报文段或者报文,发送差错报文。

CLOSE_WAIT:被动关闭,确认对端的连接终止请求,但是未向对端发送连接终止请求(可能数据没传完)。

–>收到"关闭"报文,发送FIN报文段,进入LAST_ACK状态。

–>收到任何其它报文段或者报文,发送差错报文。

LAST_ACK:数据传完,向对端发起断开连接请求后等待确认。

–>收到ACK报文段,进入CLOSED状态。

–>收到任何其它报文段或者报文,发送差错报文。

CLOSED:终点,不在连接状态。可以主动打开连接,或者等待对端的连接。
根据理解,全文背诵(能详细的讲出来),加油!
请不要:
在这里插入图片描述

  • 68
    点赞
  • 495
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值