第 16 题:谈谈你对 TCP 三次握手和四次挥手的理解
https://juejin.im/post/5c078058f265da611c26c235

4次挥手中,如果没有(稍等,还有最后一个包),那是不是就是三次挥手???
4次挥手中,如果没有(稍等,还有最后一个包),那是不是就是三次挥手???
不是的,当A告诉B,要关闭的时候,B可能还有一个包正在传输中,所以是等正在传输中的这个包传输完毕之后再回复A一下,我的图中表述的有点问题
4次挥手中,如果没有(稍等,还有最后一个包),那是不是就是三次挥手???
由于TCP连接是全双工的,因此每个方向都必须单独进行关闭,所以即使没有最后一个包,也需要先回复断开连接的请求,然后再发送关闭请求
男:我要挂了哦 女:等哈,我还要敷面膜 女:我敷完了,现在可以挂了 男:我舍不得挂,你挂吧 女:好吧,我挂了 男:等了2MSL听见嘟嘟嘟的声音后挂断
字挺好看的
男:我要挂了哦 女:等哈,我还要敷面膜 女:我敷完了,现在可以挂了 男:我舍不得挂,你挂吧 女:好吧,我挂了 男:等了2MSL听见嘟嘟嘟的声音后挂断
这个可是有点厉害了
TCP三次握手:1、客户端发送syn包到服务器,等待服务器确认接收。2、服务器确认接收syn包并确认客户的syn,并发送回来一个syn+ack的包给客户端。3、客户端确认接收服务器的syn+ack包,并向服务器发送确认包ack,二者相互建立联系后,完成tcp三次握手。四次握手就是中间多了一层 等待服务器再一次响应回复相关数据的过程
三次握手之所以是三次是保证client和server均让对方知道自己的接收和发送能力没问题而保证的最小次数。
第一次client => server 只能server判断出client具备发送能力
第二次 server => client client就可以判断出server具备发送和接受能力。此时client还需让server知道自己接收能力没问题于是就有了第三次
第三次 client => server 双方均保证了自己的接收和发送能力没有问题
其中,为了保证后续的握手是为了应答上一个握手,每次握手都会带一个标识 seq,后续的ACK都会对这个seq进行加一来进行确认。
- MSL
Maximum Segment Lifetime,译为“报文最大生存时间”。RFC 793中规定MSL为2分钟,实际应用中常用的是30秒,1分钟和2分钟等
- 为什么是
2MSL
2MSL即两倍的MSL,TCP的TIME_WAIT状态也称为2MSL等待状态。
当TCP的一端发起主动关闭,在发出最后一个ACK包后,即第3次握手完成后发送了第四次握手的ACK包后就进入了TIME_WAIT状态,必须在此状态上停留两倍的MSL时间。
等待2MSL时间主要目的是怕最后一个ACK包对方没收到,那么对方在超时后将重发第三次握手的FIN包,主动关闭端接到重发的FIN包后可以再发一个ACK应答包。
在TIME_WAIT状态时两端的端口不能使用,要等到2MSL时间结束才可继续使用。
当连接处于2MSL等待阶段时任何迟到的报文段都将被丢弃。不过在实际应用中可以通过设置SO_REUSEADDR选项达到不必等待2MSL时间结束再使用此端口。
参考来源:https://blog.csdn.net/overstack/article/details/8833894

4次挥手中,如果没有(稍等,还有最后一个包),那是不是就是三次挥手???
是的,我抓包看过。

@pzimao 请问你截图这个是啥工具喔
@pzimao 请问你截图这个是啥工具喔
FastStone
@IAMSBLOL 这个图最后断开链接是不是画反了?
为什么还需要等2msl呢?3msl不可以吗?还是本身就有这个机制
男:我要挂了哦 女:等哈,我还要敷面膜 女:我敷完了,现在可以挂了 男:我舍不得挂,你挂吧 女:好吧,我挂了 男:等了2MSL听见嘟嘟嘟的声音后挂断
这个可是有点厉害了
真实
一、三次握手讲解
- 客户端发送位码为syn=1,随机产生seq number=1234567的数据包到服务器,服务器由SYN=1知道客户端要求建立联机(客户端:我要连接你)
- 服务器收到请求后要确认联机信息,向A发送ack number=(客户端的seq+1),syn=1,ack=1,随机产生seq=7654321的包(服务器:好的,你来连吧)
- 客户端收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,客户端会再发送ack number=(服务器的seq+1),ack=1,服务器收到后确认seq值与ack=1则连接建立成功。(客户端:好的,我来了)
二、为什么http建立连接需要三次握手,不是两次或四次?
答:三次是最少的安全次数,两次不安全,四次浪费资源;
三、TCP关闭连接过程
-
Client向Server发送FIN包,表示Client主动要关闭连接,然后进入FIN_WAIT_1状态,等待Server返回ACK包。此后Client不能再向Server发送数据,但能读取数据。
-
Server收到FIN包后向Client发送ACK包,然后进入CLOSE_WAIT状态,此后Server不能再读取数据,但可以继续向Client发送数据。
-
Client收到Server返回的ACK包后进入FIN_WAIT_2状态,等待Server发送FIN包。
-
Server完成数据的发送后,将FIN包发送给Client,然后进入LAST_ACK状态,等待Client返回ACK包,此后Server既不能读取数据,也不能发送数据。
-
Client收到FIN包后向Server发送ACK包,然后进入TIME_WAIT状态,接着等待足够长的时间(2MSL)以确保Server接收到ACK包,最后回到CLOSED状态,释放网络资源。
-
Server收到Client返回的ACK包后便回到CLOSED状态,释放网络资源。
四、为什么要四次挥手?
TCP是全双工信道,何为全双工就是客户端与服务端建立两条通道,通道1:客户端的输出连接服务端的输入;通道2:客户端的输入连接服务端的输出。两个通道可以同时工作:客户端向服务端发送信号的同时服务端也可以向客户端发送信号。所以关闭双通道的时候就是这样:
客户端:我要关闭输入通道了。 服务端:好的,你关闭吧,我这边也关闭这个通道。
服务端:我也要关闭输入通道了。 客户端:好的你关闭吧,我也把这个通道关闭。
原文地址
作者:猪哥66 链接:https://www.imooc.com/article/287873 来源:慕课网 本文原创发布于慕课网 ,转载请注明出处,谢谢合作
@GuoYuFu123 四次挥手中,A等待2MSL应该从A发送第四次报文后开始等,你的图看起来像B关闭了才开始等
两次握手 (不安全,都没考量一下,万一加到的是个铁憨憨呢)
- 男:我喜欢你!加个微信吧
- 女:通过好友验证,开始交往。
三次握手 (安全、高效)
- 男:我喜欢你!可以加个微信吗?
- 女:长得还不错。是个渣男。我扫你。
- 通过好友验证,开始交往。
四次握手(浪费时间,影响效率)
- 男:我喜欢你!可以加个微信吗?
- 女:让我考虑一下。我去问下姐妹意见。
- 女:我考虑好了,我们加微信吧?
- 通过好友验证,开始交往。
四次挥手
- 男:分手!
- 女:呵呵,渣男!滚!将对方微信拉黑。
- 男:那你是同意了吗?(消息已发出,但被对方拒收了)继续等待对方回复确认分手。
- 女:经过一阵痛苦煎熬之后,好吧,分手吧。请把我送你的东西还回来。
- 男:快递寄出归还物品。等待2MSL,确认对方收到货物之后,删除对方。
- 女:收到货物,伤心欲绝,删除对方。释放自己单身资源。
三次握手
在TCP/IP协议中,TCP 协议提供可靠的连接服务,连接是通过三次握手进行初始化的。
(1)第一次握手:Client将同步标志位SYN设置为1,随机生成一个序列号x,并将数据包发送给Server。此时Client进入SYN_SENT状态,等待Server确认。 (2)第二次握手:Server接收到数据包之后,由SYN=1得知这是Client请求建立连接。Server将同步标志位SYN设置为1,将确认标志位ACK设置为1,ack = x+1,随机生成一个序列号y,并将数据包发送给Client确认请求。此时Server进入SYN_RCVD状态。(半连接列队) (3)第三次握手:Client接收到数据包后,确认ack是否为x+1,如果是则将确认标志位ACK设置为1,ack=y+1,发送给Server。此时Client状态为ESTABLISHED。Server接收到数据包之后检查ack是否为y+1,如果是则成功建立连接,Serve状态进入ESTABLISHED,完成三次握手。(全连接列队)
ISN:即Initial Sequence Number(初始序列号),在三次握手的过程当中,双方会用过SYN报文来交换彼此的 ISN。 ISN 并不是一个固定的值,而是每 4 ms 加一,溢出则回到 0,这个算法使得猜测 ISN 变得很困难。那为什么要这么做? 如果 ISN 被攻击者预测到,要知道源 IP 和源端口号都是很容易伪造的,当攻击者猜测 ISN 之后,直接伪造一个 RST 后,就可以强制连接关闭的,这是非常危险的。 而动态增长的 ISN 大大提高了猜测 ISN 的难度。
四次挥手 (1)第一次挥手:Client向Server发送FIN标志,用于关闭Client到Server的数据传送,并发送序列号a,进入FIN_WAIT_1状态。这表示Client告诉Server我已经没有数据要发给你了。 (2)第二次挥手:Server接收到FIN标志后,发送一个ack=a+1,告知Client它已经接收到了关闭请求,进入CLOSE_WAIT状态。Clinet接收到回应后进入FIN_WAIT_2状态。 (3)第三次挥手:Server发送FIN标志,用于关闭Server到Client的数据传送,并发出序列号b,进入LAST_ACK状态。这表示Server告诉Client我也没有数据要发送给你了。 (4)第四次挥手:Client接收到FIN标志后,发送一个ack=b+1,告知Server它已经接收到请求关闭,进入TIME_WAIT状态。Server接收到回应进入CLOSED状态。等待2MSL后,Client依然没有收到其他回复,则也进入CLOSED。
三次握手:
Browser:先告诉服务器 “我要开始发起请求了,你那边可以吗?”
Server:服务器回复浏览器 “没问题,你发吧!”
Browser:告诉服务器 “好的,那我开始发了。”
四次挥手:
Browser:先告诉服务器 “我数据都发完了,你可以关闭连接了。”
Server:回复浏览器 “我先看看我这边还有没有数据没传完。”
Server:确认过以后,再次回复浏览器 “我这边数据传输完成了,你可以关闭连接了。”
Browser:告诉服务器 “好的,那我真的关闭了。你不用回复我了。”
Server又等了2MSL,确认确实没有再收到请求了,才会真的关闭TCP连接。
有个疑问请教各位大佬?
Http1.x开启了keep-alive,那么是不是一直都不会有挥手的操作?
说说 TCP 三次握手过程
- 第一次握手:建立连接时,客户端发送 SYN 包(seq=x)到服务器,并进入 SYN_SENT 状态, 等待服务器确认。(SYN:同步序列编号,Synchronize Sequence Numbers);
- 第二次握手:服务器收到 SYN 包,必须确认客户的 SYN(ack=x+1),同时自己也发送一个 SYN 包(seq=y),即 SYN + ACK 包,此时服务器进入 SYN_RECEVED 状态;
- 第三次握手:客户端收到服务器的 SYN + ACK 包,向服务器发送确认包 ACK(ack=y+1),此包发送完毕,客户端和服务器端进入 ESTABLISHED(TCP 连接成功)状态,完成三次握手。
TCP 3-Way Handshake (SYN, SYN-ACK,ACK),TCP 三次握手流程图

TCP Header

TCP 有6中标志位:
- SYN(synchronous 建立连接)
- ACK(acknowledgement 确认)
- PSH(push 传送)
- FIN(finish 结束)
- RST(reset 重置)
- URG(urgent 紧急)
另外数据包:
- Sequence number(顺序号码)
- Acknowledge number(确认号码)
- 第一次握手中 SYN = 1,代表客户端 Client 要建立连接,同时随机产生 seq(Sequence number)= x 的数据包,然后传输到 Server;
- Server 收到 Client 的信息,通过 SYN = 1 知道是要建立连接,然后向 Client 发送信息,ACK = 1 代表确认,ack(Acknowledge number)= x + 1,SYN = 1 代表建立连接,随机产生 seq = y 的数据包;
- Clien 收到 Server 的信息,通过 SYN = 1 知道是要建立连接,然后检查 ack 是否正确,即第一次发送的 seq + 1,同时检查 ACK 是否为 1,若正确,Client 再发送 ack = y + 1,ACK = 1 到 Server,Server 收到确认 seq 值和 ACK = 1 后则连接建立成功。
A: 我完事了 B: 我知道了 B: 我完事了 A: 好,咱关吧
TCP 连接的时候为什么要三次握手?因为三次握手才能保证双方能听到(接收)和回应(发送)数据。 想象一下在一个很嘈杂的环境中(数据的传输就是在这种环境下),两个人之间对话的开始。 A:B,你好啊,你能听到我讲话吗? B:A,你好啊,我听到了,你呢? A:我也听到了。

三次握手: client:约不约???!!!(syn=1) server:约约约!!!(ack=1,syn=1) client:好的,我来找你!!!(ack=1)
四次挥手: client:老子要离职!!!(FIN=1) server:OK,你要离职是吧,我马上给你走程序!程序完了我通知你!!(ACK=1) server:程序走完了,文件发给你了,你最后确认一下(FIN=1) client:OK,确认完毕,关机跑路(ACK=1)
为什么还需要等2msl呢?3msl不可以吗?还是本身就有这个机制
RFC文档规定的吧