Moosphan/Android-Daily-Interview

2019-08-26:谈一谈TCP/IP三次握手,四次挥手?

MoJieBlog opened this issue · 10 comments

2019-08-26:谈一谈TCP/IP三次握手,四次挥手?

一切都是为了数据安全的传输。
拟人化,想象一下两个人在一片漆黑的世界里,如何用声音交流。

A:你好吗? ,B听见 (第一次握手,B知道A会说话,会听吗?A知道B会听,会说吗?)
B:谢谢!我很好,你呢?,A听见(第二次握手,A知道B能听见,会说话。B知道A会说,但是会听吗?)
A:我也很好,你准备干什么?,B听见(A,B双方均确认对方会说会听,然后开始交流)。

......

A:我要走了,你还有事吗?,A等待(第一次挥手)
B:嗯!稍等我想想 A:收到,等待中(第二次挥手)
B:没事了,走吧?B等待中(第三次)
A:好的,那走吧!B走了,A等了一会B没声了,A也走了(第四次)

个人理解,相互交流。

TCP的三次握手的举例子
发送方:喂,听得到吗?
接收方:听得到,你听得到我吗?
发送方:听到了,我们可以说话了。

那么为什么必须是三次握手?
第一次握手:A向B发送消息后,B收到消息。B可确认A的发信能力和B的收信能力
第二次握手:B向A发送消息,A收到消息。A可确认A的发信能力和收信能力,A也可确认B的收信能力和发信能力
第三次握手:A向B发送消息,B接收到消息。B可确认A的收信能力和B的发信能力
经过三次握手,A和B都能确认自己和对方的收发信息能力,相当于建立了彼此的信任,所以就可以开始通讯了

三次握手是建立连接,四次握手是断开连接

tcp三次握手举例:
a发送者:hi,听的到?
b接收方:听的到,你能听到我?
a:可以,我们可以交流了。
四次挥手举例:
a发送者:我要走了,你还有事?a等待中
b接收方:嗯,稍等我想想;a:收到,等待
b:没事了,走吗,b等待中
a:好的,拿走吧!b走了,a等了一会b没有声音了,a也走了

形象比喻都清楚,但是具体的每次连接中像syn 啊 seq啊 这些具体的含义,作用有没有专门研究过这儿的人来详细说一下

形像比喻都清楚,但是具體的每次連接中像syn啊seq啊這些具體的含義,作用有沒有專門研究過這兒的人來詳細說一下

tcp的6种标志位的分别代表:

SYN(synchronous建立联机)

ACK(acknowledgement 确认)

PSH(push传送)

FIN(finish结束)

RST(reset重置)

URG(urgent紧急)

Sequence number(顺序号码)

Acknowledge number(确认号码)

其实为了能快速安全的链接或者关闭,建链中的这些syn,fin等都是相互约定的一些交互状态码,外加一些随机数,相互叠加校验,数据都不会太长,也不会有多复杂。

面试现在一般都要详细流程,比如连接过程中,你每次握手发送的具体数据

面试现在一般都要详细流程,比如连接过程中,你每次握手发送的具体数据 这个大家都怎么回答的?

常见的 TCP 中的头部数据表示

  • ACK:该位为 1 时,「确认应答」的字段变为有效,TCP 规定除了最初建立连接时的 SYN 包之外该位必须设置为 1
  • SYN:该位为 1 时,表示希望建立连接,并在其「序列号」的字段进行序列号初始值的设定
  • RST:该位为 1 时,表示 TCP 连接中出现异常必须强制断开连接
  • 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, 接着把 SYNACK 标志位置为 1。最后把该报文发给客户端,该报文也不包含应用层数据,之后服务端处于 SYN-RCVD 状态。
  • 第三个报文 —— ACK 报文

    • 客户端收到服务端报文后,还要向服务端回应最后一个应答报文,首先该应答报文 TCP 首部 ACK 标志位置为 1 ,其次「确认应答号」字段填入 server_isn + 1 ,最后把报文发送给服务端,这次报文可以携带客户到服务器的数据,之后客户端处于 ESTABLISHED 状态。

服务器收到客户端的应答报文后,也进入 ESTABLISHED 状态,此时 TCP 建立结束,双方可以收发数据。

为什么是三次握手?不是两次、四次?

  • 三次握手才能保证双方具有接收和发送的能力
  • 三次握手才可以阻止重复历史连接的初始化
  • 三次握手才可以同步双方的初始序列号
  • 三次握手才可以避免资源浪费

TCP 四次挥手过程

客户端主动关闭连接 —— TCP 四次挥手

客户端主动关闭连接 —— TCP 四次挥手

  • 客户端打算关闭连接,此时会发送一个 TCP 首部 FIN 标志位被置为 1 的报文,也即 FIN 报文,之后客户端进入 FIN_WAIT_1 状态。
  • 服务端收到该报文后,就向客户端发送 ACK 应答报文,接着服务端进入 CLOSED_WAIT 状态。
  • 客户端收到服务端的 ACK 应答报文后,之后进入 FIN_WAIT_2 状态。
  • 等待服务端处理完数据后,也向客户端发送 FIN 报文,之后服务端进入 LAST_ACK 状态。
  • 客户端收到服务端的 FIN 报文后,回一个 ACK 应答报文,之后进入 TIME_WAIT 状态
  • 服务器收到了 ACK 应答报文后,就进入了 CLOSED 状态,至此服务端已经完成连接的关闭。
  • 客户端在经过 2MSL 一段时间后,自动进入 CLOSED 状态,至此客户端也完成连接的关闭。

客户端和服务端都需要一个 FIN 和一个 ACK,因此通常被称为四次挥手

这里一点需要注意是:主动关闭连接的,才有 TIME_WAIT 状态。

为什么挥手需要四次?

回顾上方四次挥手双方发 FIN 包的过程,就能理解为什么需要四次了。

  • 关闭连接时,客户端向服务端发送 FIN 时,仅仅表示客户端不再发送数据了但是还能接收数据。
  • 服务器收到客户端的 FIN 报文时,先回一个 ACK 应答报文,而服务端可能还有数据需要处理和发送,等服务端不再发送数据时,才发送 FIN 报文给客户端来表示同意现在关闭连接。

从上面过程可知,服务端通常需要等待完成数据的发送和处理,所以服务端的 ACKFIN 一般都会分开发送,从而比三次握手导致多了一次。

引用文章:

https://www.cnblogs.com/xiaolincoding/p/12638546.html

TCP建立连接三次握手是为了保证服务端和客户端的收发能力都没有问题
四次挥手 在客户端主动断开连接的时候会发一个finsh包告诉服务端要关闭连接 服务端收到客户端的finsh包后马上告诉客户端已经接收到客户端的断开连接了 但是服务端可能还会有一些数据需要给客户端发送 服务端在发完数据之后才给客户端发送finsh包 表达后面不会再给客户端发送数据了 客户端收到服务端的finsh后再发送一次数据给服务端表达明白