Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

第 16 题:谈谈你对 TCP 三次握手和四次挥手的理解 #15

Open
jinggk opened this issue Feb 19, 2019 · 33 comments
Open

第 16 题:谈谈你对 TCP 三次握手和四次挥手的理解 #15

jinggk opened this issue Feb 19, 2019 · 33 comments
Labels

Comments

@jinggk
Copy link

jinggk commented Feb 19, 2019

https://juejin.im/post/5c078058f265da611c26c235

@GuoYuFu123
Copy link

image

@phantomlution
Copy link

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

@GuoYuFu123
Copy link

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

不是的,当A告诉B,要关闭的时候,B可能还有一个包正在传输中,所以是等正在传输中的这个包传输完毕之后再回复A一下,我的图中表述的有点问题

@fisher-zh
Copy link

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

由于TCP连接是全双工的,因此每个方向都必须单独进行关闭,所以即使没有最后一个包,也需要先回复断开连接的请求,然后再发送关闭请求

@zhuziyi1989
Copy link

男:我要挂了哦
女:等哈,我还要敷面膜
女:我敷完了,现在可以挂了
男:我舍不得挂,你挂吧
女:好吧,我挂了
男:等了2MSL听见嘟嘟嘟的声音后挂断

@cyh41
Copy link

cyh41 commented Mar 6, 2019

字挺好看的

@haoshuai666
Copy link

男:我要挂了哦
女:等哈,我还要敷面膜
女:我敷完了,现在可以挂了
男:我舍不得挂,你挂吧
女:好吧,我挂了
男:等了2MSL听见嘟嘟嘟的声音后挂断

这个可是有点厉害了

@yygmind yygmind changed the title 关于第16题的见解 第 16 题:谈谈你对 TCP 三次握手和四次挥手的理解 Apr 26, 2019
@AlertTed
Copy link

TCP三次握手:1、客户端发送syn包到服务器,等待服务器确认接收。2、服务器确认接收syn包并确认客户的syn,并发送回来一个syn+ack的包给客户端。3、客户端确认接收服务器的syn+ack包,并向服务器发送确认包ack,二者相互建立联系后,完成tcp三次握手。四次握手就是中间多了一层 等待服务器再一次响应回复相关数据的过程

@LeoMelody
Copy link

三次握手之所以是三次是保证client和server均让对方知道自己的接收和发送能力没问题而保证的最小次数。

第一次client => server 只能server判断出client具备发送能力
第二次 server => client client就可以判断出server具备发送和接受能力。此时client还需让server知道自己接收能力没问题于是就有了第三次
第三次 client => server 双方均保证了自己的接收和发送能力没有问题

其中,为了保证后续的握手是为了应答上一个握手,每次握手都会带一个标识 seq,后续的ACK都会对这个seq进行加一来进行确认。

@w3cmark
Copy link

w3cmark commented Jul 13, 2019

  • 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

@mongonice
Copy link

mongonice commented Jul 16, 2019

挺不错的

@IAMSBLOL
Copy link

image

@pzimao
Copy link

pzimao commented Jul 27, 2019

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

是的,我抓包看过。

@pzimao
Copy link

pzimao commented Jul 27, 2019

clipboard

@w3cmark
Copy link

w3cmark commented Jul 27, 2019

@pzimao 请问你截图这个是啥工具喔

@pzimao
Copy link

pzimao commented Jul 31, 2019

@pzimao 请问你截图这个是啥工具喔

FastStone

@yingye
Copy link

yingye commented Aug 1, 2019

@IAMSBLOL 这个图最后断开链接是不是画反了?

@bertGo
Copy link

bertGo commented Aug 26, 2019

为什么还需要等2msl呢?3msl不可以吗?还是本身就有这个机制

@1326023569
Copy link

男:我要挂了哦
女:等哈,我还要敷面膜
女:我敷完了,现在可以挂了
男:我舍不得挂,你挂吧
女:好吧,我挂了
男:等了2MSL听见嘟嘟嘟的声音后挂断

这个可是有点厉害了

真实

@vinsiny
Copy link

vinsiny commented Nov 1, 2019

一、三次握手讲解

  1. 客户端发送位码为syn=1,随机产生seq number=1234567的数据包到服务器,服务器由SYN=1知道客户端要求建立联机(客户端:我要连接你)
  2. 服务器收到请求后要确认联机信息,向A发送ack number=(客户端的seq+1),syn=1,ack=1,随机产生seq=7654321的包(服务器:好的,你来连吧)
  3. 客户端收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,客户端会再发送ack number=(服务器的seq+1),ack=1,服务器收到后确认seq值与ack=1则连接建立成功。(客户端:好的,我来了)

二、为什么http建立连接需要三次握手,不是两次或四次?

答:三次是最少的安全次数,两次不安全,四次浪费资源;

三、TCP关闭连接过程

  1. Client向Server发送FIN包,表示Client主动要关闭连接,然后进入FIN_WAIT_1状态,等待Server返回ACK包。此后Client不能再向Server发送数据,但能读取数据。

  2. Server收到FIN包后向Client发送ACK包,然后进入CLOSE_WAIT状态,此后Server不能再读取数据,但可以继续向Client发送数据。

  3. Client收到Server返回的ACK包后进入FIN_WAIT_2状态,等待Server发送FIN包。

  4. Server完成数据的发送后,将FIN包发送给Client,然后进入LAST_ACK状态,等待Client返回ACK包,此后Server既不能读取数据,也不能发送数据。

  5. Client收到FIN包后向Server发送ACK包,然后进入TIME_WAIT状态,接着等待足够长的时间(2MSL)以确保Server接收到ACK包,最后回到CLOSED状态,释放网络资源。

  6. Server收到Client返回的ACK包后便回到CLOSED状态,释放网络资源。

四、为什么要四次挥手?

TCP是全双工信道,何为全双工就是客户端与服务端建立两条通道,通道1:客户端的输出连接服务端的输入;通道2:客户端的输入连接服务端的输出。两个通道可以同时工作:客户端向服务端发送信号的同时服务端也可以向客户端发送信号。所以关闭双通道的时候就是这样:

客户端:我要关闭输入通道了。
服务端:好的,你关闭吧,我这边也关闭这个通道。

服务端:我也要关闭输入通道了。
客户端:好的你关闭吧,我也把这个通道关闭。

原文地址

作者:猪哥66
链接:https://www.imooc.com/article/287873
来源:慕课网
本文原创发布于慕课网 ,转载请注明出处,谢谢合作

@mjyg
Copy link

mjyg commented Nov 11, 2019

@GuoYuFu123 四次挥手中,A等待2MSL应该从A发送第四次报文后开始等,你的图看起来像B关闭了才开始等

@cpg0525
Copy link

cpg0525 commented Dec 10, 2019

两次握手 (不安全,都没考量一下,万一加到的是个铁憨憨呢)

  • 男:我喜欢你!加个微信吧
  • 女:通过好友验证,开始交往。

三次握手 (安全、高效)

  • 男:我喜欢你!可以加个微信吗?
  • 女:长得还不错。是个渣男。我扫你。
  • 通过好友验证,开始交往。

四次握手(浪费时间,影响效率)

  • 男:我喜欢你!可以加个微信吗?
  • 女:让我考虑一下。我去问下姐妹意见。
  • 女:我考虑好了,我们加微信吧?
  • 通过好友验证,开始交往。

四次挥手

  • 男:分手!
  • 女:呵呵,渣男!滚!将对方微信拉黑。
  • 男:那你是同意了吗?(消息已发出,但被对方拒收了)继续等待对方回复确认分手。
  • 女:经过一阵痛苦煎熬之后,好吧,分手吧。请把我送你的东西还回来。
  • 男:快递寄出归还物品。等待2MSL,确认对方收到货物之后,删除对方。
  • 女:收到货物,伤心欲绝,删除对方。释放自己单身资源。

@RoeyXie
Copy link

RoeyXie commented Jul 30, 2020

三次握手

在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。

@xsfxtsxxr
Copy link

三次握手:

Browser:先告诉服务器 “我要开始发起请求了,你那边可以吗?”
Server:服务器回复浏览器 “没问题,你发吧!”
Browser:告诉服务器 “好的,那我开始发了。”

四次挥手:

Browser:先告诉服务器 “我数据都发完了,你可以关闭连接了。”
Server:回复浏览器 “我先看看我这边还有没有数据没传完。”
Server:确认过以后,再次回复浏览器 “我这边数据传输完成了,你可以关闭连接了。”
Browser:告诉服务器 “好的,那我真的关闭了。你不用回复我了。”

Server又等了2MSL,确认确实没有再收到请求了,才会真的关闭TCP连接。

有个疑问请教各位大佬?

Http1.x开启了keep-alive,那么是不是一直都不会有挥手的操作?

@Moon-Future
Copy link

说说 TCP 三次握手过程

  1. 第一次握手:建立连接时,客户端发送 SYN 包(seq=x)到服务器,并进入 SYN_SENT 状态, 等待服务器确认。(SYN:同步序列编号,Synchronize Sequence Numbers);
  2. 第二次握手:服务器收到 SYN 包,必须确认客户的 SYN(ack=x+1),同时自己也发送一个 SYN 包(seq=y),即 SYN + ACK 包,此时服务器进入 SYN_RECEVED 状态;
  3. 第三次握手:客户端收到服务器的 SYN + ACK 包,向服务器发送确认包 ACK(ack=y+1),此包发送完毕,客户端和服务器端进入 ESTABLISHED(TCP 连接成功)状态,完成三次握手。

TCP 3-Way Handshake (SYN, SYN-ACK,ACK),TCP 三次握手流程图

tcp-3-way-handshake

TCP Header

TCP-Header-Format

TCP 有6中标志位:

  • SYN(synchronous 建立连接)
  • ACK(acknowledgement 确认)
  • PSH(push 传送)
  • FIN(finish 结束)
  • RST(reset 重置)
  • URG(urgent 紧急)

另外数据包:

  • Sequence number(顺序号码)
  • Acknowledge number(确认号码)
  1. 第一次握手中 SYN = 1,代表客户端 Client 要建立连接,同时随机产生 seq(Sequence number)= x 的数据包,然后传输到 Server;
  2. Server 收到 Client 的信息,通过 SYN = 1 知道是要建立连接,然后向 Client 发送信息,ACK = 1 代表确认,ack(Acknowledge number)= x + 1SYN = 1 代表建立连接,随机产生 seq = y 的数据包;
  3. Clien 收到 Server 的信息,通过 SYN = 1 知道是要建立连接,然后检查 ack 是否正确,即第一次发送的 seq + 1,同时检查 ACK 是否为 1,若正确,Client 再发送 ack = y + 1ACK = 1 到 Server,Server 收到确认 seq 值和 ACK = 1 后则连接建立成功。

@865077695
Copy link

A: 我完事了
B: 我知道了
B: 我完事了
A: 好,咱关吧

@xiaocongWang
Copy link

TCP 连接的时候为什么要三次握手?因为三次握手才能保证双方能听到(接收)和回应(发送)数据。
想象一下在一个很嘈杂的环境中(数据的传输就是在这种环境下),两个人之间对话的开始。
A:B,你好啊,你能听到我讲话吗?
B:A,你好啊,我听到了,你呢?
A:我也听到了。

@xiaolannuoyi
Copy link

image

@3104026951
Copy link

三次握手:
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)

@wd2010
Copy link

wd2010 commented Apr 24, 2021

为什么还需要等2msl呢?3msl不可以吗?还是本身就有这个机制

RFC文档规定的吧

@shifengdiy
Copy link

tcp三次握手:

三次握手

  1. 客户端想要建立连接,发起一个syn=1 seq=x的tcp包,表示想要建立连接
  2. 服务端收到包,表示可以建立连接,回复一个 ack=1 syn=1 seq=y ACKnum=x+1的包同意连接
  3. 客户端收到确认包之后,了解到可以建立连接;再次发送包 ac1 syn=0 ACKnum=y+1确认建立连接;客户端进入连接状态,服务器收到包之后也进入连接状态 tcp连接建立

数据传输

传输过程中,tcp连接会一次性发送若干个包测试连接速度,根据连接速度调整tcp包的发送频率

四次挥手

  1. 客户端需要断开连接,发起一个fin=1 seq=x的包,请求断开连接
  2. 服务端收到请求断开的包,发送一个ack=1 ACKnum=x+1的包表示请求已确认,但是这期间可能有剩余数据需要发送,将剩余的数据发送完毕
  3. 服务端检查所有数据都已发送完毕,发送一个find=1 seq=y的包表示同意断开请求
  4. 客户端收到同意断开请求的包,发送ack=1 ACKnum=y+1的表示确认断开连接
  5. 最后阶段,服务端收到最后一个包之后,断开连接,客户端在发送最后一个包之后,等待两个最大生命周期,然后也断开连接 tpc连接断开

@yuanyiying123
Copy link

三次握手
客户端发送 连接请求syn报文, 服务器端 接收到syn报文后回复 syn+ack确认报文,表示可以连接 ,客户端接收到后回复ack报文表示知晓(为了表明客户端的收信能力),连接就此建立。
例子 借钱:
a : b,我想借钱
b : 知晓,可以借钱 (a未答复时,b不知道a能不能收到信息,不安全)
a: 收到。
a - b连接 可以借/收钱了
四次挥手
客户端发送fin报文表示想要终止连接,服务端收到信息,发送ack报文表示了解(此时可能有其他报文未发送完毕),服务端发送fin报文表示自己也可以终止连接了。客户端知晓后发送ACK报文并定义定时器,在两个通信最大时长之后自动关闭自身连接,服务端在收到ack报文时关闭自身连接。
例子 挂电话
a: 不说了,挂了
b:要的
b:你要balabalblabla哈 (继续说未说完的话),就这样,拜拜
a: 拜拜
嘟嘟嘟 连接关闭
断开连接的不一定是客户端,也可能是服务器端,谁先发送断开请求,谁就可以当做客户端

@gdkttt
Copy link

gdkttt commented Mar 13, 2023

如果 B 机器突然重启,那么 B 机器与 A 机器之间的 TCP 连接将被断开。此时,A 机器将无法与 B 机器进行通信。

当 A 机器试图向 B 机器发送数据时,TCP 协议会发送一个数据包(称为“探测包”)到 B 机器,以检测连接是否仍然存在。如果探测包能够成功到达 B 机器,并且 B 机器也能够正确地响应,那么连接仍然有效,A 机器可以继续发送数据。

如果探测包无法到达 B 机器,或者 B 机器无法响应,那么连接将被视为已经断开。此时,A 机器的 TCP 状态将变为“TIME_WAIT”状态,表示连接已经关闭,但是仍然需要等待一段时间,以确保所有的数据包都已经被接收到。在 TIME_WAIT 状态下,A 机器将继续发送一些控制信息,以保证连接的完整性。这个过程通常需要等待一段时间(通常是几分钟),在等待时间结束后,A 机器将关闭连接。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests