TCP 三次握手和四次挥手(传输层)

打印 上一主题 下一主题

主题 969|帖子 969|积分 2907

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
建立连接-TCP 三次握手


建立一个 TCP 连接需要“三次握手”,缺一不可:


  • 一次握手:客户端发送带有 SYN(SEQ=x) 标志的数据包 -> 服务端,然后客户端进入 SYN_SEND 状态,等待服务端简直认;
  • 二次握手:服务端发送带有 SYN+ACK(SEQ=y,ACK=x+1) 标志的数据包 –> 客户端,然后服务端进入 SYN_RECV 状态;
  • 三次握手:客户端发送带有 ACK(ACK=y+1) 标志的数据包 –> 服务端,然后客户端和服务端都进入ESTABLISHED 状态,完成 TCP 三次握手。
当建立了 3 次握手之后,客户端和服务端就可以传输数据啦!
什么是半连接队列和全连接队列?

在 TCP 三次握手过程中,Linux 内核会维护两个队列来管理连接哀求:

  • 半连接队列(也称 SYN Queue):当服务端收到客户端的 SYN 哀求时,此时两边还没有完全建立连接,它会把半连接状态的连接放在半连接队列。
  • 全连接队列(也称 Accept Queue):当服务端收到客户端对 ACK 响应时,意味着三次握手乐成完成,服务端会将该连接从半连接队列移动到全连接队列。如果未收到客户端的 ACK 响应,会举行重传,重传的等待时间通常是指数增长的。如果重传次数超过系统规定的最大重传次数,系统将从半连接队列中删除该连接信息。
这两个队列的存在是为了处置处罚并发连接哀求,确保服务端可以大概有效地管理新的连接哀求。另外,新的连接哀求被拒绝或忽略除了和每个队列的大小限制有关系之外,还和许多其他因素有关系,这里就不详细先容了,整体逻辑比力复杂。
为什么要三次握手?

三次握手的目的是建立可靠的通讯信道,说到通讯,简单来说就是数据的发送与吸收,而三次握手最主要的目的就是两边确认本身与对方的发送与吸收是正常的。

  • 第一次握手:Client 什么都不能确认;Server 确认了对方发送正常,本身吸收正常
  • 第二次握手:Client 确认了:本身发送、吸收正常,对方发送、吸收正常;Server 确认了:对方发送正常,本身吸收正常
  • 第三次握手:Client 确认了:本身发送、吸收正常,对方发送、吸收正常;Server 确认了:本身发送、吸收正常,对方发送、吸收正常
三次握手就能确认两边收发功能都正常,缺一不可。
更详细的解答可以看这个:TCP 为什么是三次握手,而不是两次或四次? - 车小胖的答复 - 知乎 。
第 2 次握手传回了 ACK,为什么还要传回 SYN?

服务端传回发送端所发送的 ACK 是为了告诉客户端:“我吸收到的信息确实就是你所发送的信号了”,这表明从客户端到服务端的通讯是正常的。回传 SYN 则是为了建立并确认从服务端到客户端的通讯。
   SYN 同步序列编号(Synchronize Sequence Numbers) 是 TCP/IP 建立连接时利用的握手信号。在客户机和服务端之间建立正常的 TCP 网络连接时,客户机起首发出一个 SYN 消息,服务端利用 SYN-ACK 应答表示吸收到了这个消息,最后客户机再以 ACK(Acknowledgement)消息响应。这样在客户机和服务端之间才能建立起可靠的 TCP 连接,数据才可以在客户机和服务端之间传递。
  三次握手过程中可以携带数据吗?

在 TCP 三次握手过程中,第三次握手是可以携带数据的(客户端发送完 ACK 确认包之后就进入 ESTABLISHED 状态了),这一点在 RFC 793 文档中有提到。也就是说,一旦完成了前两次握手,TCP 协议允许数据在第三次握手时开始传输。
如果第三次握手的 ACK 确认包丢失,但是客户端已经开始发送携带数据的包,那么服务端在收到这个携带数据的包时,如果该包中包含了 ACK 标记,服务端会将其视为有效的第三次握手确认。这样,连接就被以为是建立的,服务端会处置处罚该数据包,并继承正常的数据传输流程。
断开连接-TCP 四次挥手


断开一个 TCP 连接则需要“四次挥手”,缺一不可:

  • 第一次挥手:客户端发送一个 FIN(SEQ=x) 标志的数据包->服务端,用来关闭客户端到服务端的数据传送。然后客户端进入 FIN-WAIT-1 状态。
  • 第二次挥手:服务端收到这个 FIN(SEQ=X) 标志的数据包,它发送一个 ACK (ACK=x+1)标志的数据包->客户端 。然后服务端进入 CLOSE-WAIT 状态,客户端进入 FIN-WAIT-2 状态。
  • 第三次挥手:服务端发送一个 FIN (SEQ=y)标志的数据包->客户端,哀求关闭连接,然后服务端进入 LAST-ACK 状态。
  • 第四次挥手:客户端发送 ACK (ACK=y+1)标志的数据包->服务端,然后客户端进入TIME-WAIT状态,服务端在收到 ACK (ACK=y+1)标志的数据包后进入 CLOSE 状态。此时如果客户端等待 2MSL 后依然没有收到复兴,就证明服务端已正常关闭,随后客户端也可以关闭连接了。
只要四次挥手没有竣事,客户端和服务端就可以继承传输数据!
为什么要四次挥手?

TCP 是全双工通讯,可以双向传输数据。任何一方都可以在数据传送竣过后发出连接开释的关照,待对方确认后进入半关闭状态。当另一方也没有数据再发送的时间,则发出连接开释关照,对方确认后就完全关闭了 TCP 连接。
举个例子:A 和 B 打电话,通话即将竣过后。

  • 第一次挥手:A 说“我没啥要说的了”
  • 第二次挥手:B 答复“我知道了”,但是 B 可能还会有要说的话,A 不能要求 B 跟着本身的节奏竣事通话
  • 第三次挥手:于是 B 可能又巴拉巴拉说了一通,最后 B 说“我说完了”
  • 第四次挥手:A 答复“知道了”,这样通话才算竣事。
为什么不能把服务端发送的 ACK 和 FIN 合并起来,变成三次挥手?

因为服务端收到客户端断开连接的哀求时,可能另有一些数据没有发完,这时先复兴 ACK,表示吸收到了断开连接的哀求。等到数据发完之后再发 FIN,断开服务端到客户端的数据传送。
如果第二次挥手时服务端的 ACK 没有送达客户端,会怎样?

客户端没有收到 ACK 确认,会重新发送 FIN 哀求。
为什么第四次挥手客户端需要等待 2*MSL(报文段最长寿命)时间后才进入 CLOSED 状态?

第四次挥手时,客户端发送给服务端的 ACK 有可能丢失,如果服务端因为某些原因而没有收到 ACK 的话,服务端就会重发 FIN,如果客户端在 2*MSL 的时间内收到了 FIN,就会重新发送 ACK 并再次等待 2MSL,防止 Server 没有收到 ACK 而不断重发 FIN。
   MSL(Maximum Segment Lifetime) : 一个片段在网络中最大的存活时间,2MSL 就是一个发送和一个复兴所需的最大时间。如果直到 2MSL,Client 都没有再次收到 FIN,那么 Client 推断 ACK 已经被乐成吸收,则竣事 TCP 连接。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

曹旭辉

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表