TCP基础 —— 为什么建立连接需要三次握手,而断开连接则需要四次?能不能是三次?

Wesley13
• 阅读 813

一、TCP包概述

一个 segment 包含 header 和 data 两个部分,对于这篇文章需要理解的就是,Sequence number 和 Acknowledgement number) 这两个字段。TCP 的可靠传输就是基于这两个字段来实现的。 虽然文章的主旨是三次握手(three-way handshake)与四次挥手(four-way handshake),但不理解 Sequence number 和 Acknowledgement number 就无法真正的理解这两个过程。

TCP基础 —— 为什么建立连接需要三次握手,而断开连接则需要四次?能不能是三次?

Sequence number

  • 当开始一个 TCP 会话时,此时 SYN 位为 1,会生成一个随机的 Sequence number,后续使用 Sequence number 则从 Sequence number + 1 开始。
  • 其他时候,则表示为 data 部分第一位的位置,值为此位数据的 Sequence number ,即基于初始 Sequence number + 1 + offset。

其实很好理解,我们先抛开第一次生成的 Sequence number,后续的 TCP 头中的 Sequence number 都指的是 data 部分第一位的序号。比如:

  • 我这次发送的 Sequence number 为 100,数据长度为 100,
  • 那么我下一次发送的 Sequence number 就应该是 200,再假定数据长度为 50,
  • 如果要进行第三次发送,那么 Sequence number 的值应为 250。

下面的图简单的表明了发送两个连续的 segment 的 Sequence number 变化情况,忽略了TCP头,TCP头 并不计入 Length TCP基础 —— 为什么建立连接需要三次握手,而断开连接则需要四次?能不能是三次?

Acknowledgement number

  • 回复收到的最大 Sequence number + 1,表示期望收到的 Sequence number 的值。

和上面的其实一样的道理,比如收到 Sequence number 为 100,数据长度为 100,那么我们就回复 Acknowledgement number = 200。

二、三次握手过程概述

有了上面的基础,我们再开始看握手过程,TCP连接三次握手的过程如下,为了方便描述:

  • SEQ_NUM 代表 TCP header 中的 Sequence number

  • ACK_NUM 代表 TCP header 中的 Acknowledgment number

  • DATA_LEN 代表 segment 中 data 的长度

    SYN(1) ACK(0) SEQ_NUM(0) ACK_NUM(0) DATA_LEN(0) ====> <==== SYN(1) ACK(1) SEQ_NUM(100) ACK_NUM(1) DATA_LEN(0) SYN(0) ACK(1) SEQ_NUM(1) ACK_NUM(101) DATA_LEN(0) ====>

  • 连接发起方将 SYN 位设置为1,然后随机生成一个 SEQ_NUM_A,发送给被发起方。

  • 被发起方回复 ACK(1) ACK_NUM(SEQ_NUM_A+1),同时也需将 SYN 位设置为1,然后自己也随机生成一个 SEQ_NUM_B。

  • 连接发起方收到上个 segment 后,回复 ACK(1) ACK_NUM(SEQ_NUM_B+1),当被发起方收到这个 segment 后,连接建立成功。

三、可能存在的疑问

1、为什么要强调 Sequence number 和 Acknowledgement number?

假设同样是三次握手,但是很简单:

SYN(1) ACK(0)  ====>
               <====  SYN(1) ACK(1)
SYN(0) ACK(1)  ====>

看起来没问题,但实际上由于网络传输是不可靠的,如果没有 Sequence number 我们无法保证此时收到的 segment 的顺序性,也无法得知是否丢失了某个 segment。同样是一个 SYN(1) ACK(1) segment,它有可能是上一次建立连接时被发送方误认为已经丢失的 segment,甚至更特殊的情况。

在数据传输的过程中也是如此,被重发的 segment,丢失的 segment,连续发送的 100 个 segment 如果没有 Sequence number 作为保障,他们到达(或者到达不了)接收方的排列组合方式可能千奇百怪。

2、那么在 Sequence number 和 Acknowledgement number 的保障下,如何保证自己的消息被对方收到呢?

这个其实很好理解,实际上就是自己发送出去的这部分 Sequence number 被 ack 了即可,即:一去一回(实际上可以多去一回,或者可能一去多回,但这里只说最简单的情况)。

SEQ_NUM(100) DATA_LEN(100)    ====>
                              <====   ACK(200)

如果没有收到对方的 ack,或者收到的 ack 非此 segment 的 ack,则代表对方没有收到自己的消息,比如下面这个例子,此时我们能得知,对方没有收到或者暂时还没收到我们发送过去的第二个 segment。

此时也可以区分出收到的 segment 是否属于本次连接,因为在建立连接后我们会生成一个新的 Sequence number。

SEQ_NUM(100) DATA_LEN(100)    ====>
                              <====   ACK(200)
SEQ_NUM(200) DATA_LEN(100)    ====>
                              <====   ACK(200)

3、这就很好理解 TCP 连接握手为什么是三次了。

  • 发起连接方发出SYN,并收到ACK,这就是两次网络传输了。
  • 同样被连接方也发出SYN,且等待对方回复,这也是两次网络传输。

加起来难道不是四次吗?实际上被连接方将对连接方 SYN(1) 的回复和自己 SYN(1) 的请求合并了,所以建立一个 TCP 连接最少只需要经过三次网络传输。

4、那为什么 TCP 断开连接需要四次,而不是三次?

  • 发起断开方发出FIN,并收到ACK,这就是两次网络传输了。
  • 同样被断开方也发出FIN,且等待对方回复,这也是两次网络传输。

同样的逻辑分析下来,实际上也可以仅经过三次传输就断开此次连接,但为什么我们会说四次挥手呢?这是因为如果在收到FIN时,彼时还有数据未传输完,则先回复关于 FIN 的 ACK,告知对方我已经知道你要断开了。则等待传输完毕后,被断开方再发送 FIN,告知自己也已经可以断开连接。

但实际上完全可以是“三次挥手”,如果收到 FIN 时,已经没有数据要传输,则是“三次挥手”。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Easter79 Easter79
3年前
tcp编程、socket编程、redis
tcp编程(需要建立连接,三次握手,四次挥手,然后发送信息流,数据包是有序的)udp编程(知道IP、端口直接发送数据,数据包可能是无序的)1、客户端和服务器客!(http
Wesley13 Wesley13
3年前
TCP的三次握手与四次挥手
TCP的三次握手与四次挥手一、TCP(TransmissionControlProtocol传输控制协议)TCP是面向对连接,可靠的进程到进程通信的协议TCP是提供全双工服务,即数据可在同一时间双向传输二、TCP报文段(封装在IP数据报
Wesley13 Wesley13
3年前
TCP三次握手和四次挥手
建立TCP连接:三次握手TCP在传输数据之前,首先需要建立好TCP连接,后续所有数据都基于这个已建立的连接来传输,建立TCP连接的过程通常被描述为三次握手屏幕快照2020072716.44.59!TCP三次握手和四次挥手(https://s4.51cto.com/images/blog/202007/27/e095cdb6ee5e99
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
TCP连接过程及报文解析
可能大家都听过TCP建立连接时需要经历三次握手和四次挥手的。那么具体的握手挥手的过程是怎么样的呢?这篇文章就通过WireShark抓包来了解TCP连接建立和断开的过程。实验方法:写一段简单的代码代码客户端和服务端,分别部署,让客户端主动像服务器发起连接,随后断开。让WireShark抓股这个过程中产生了哪些包,并对其分析。(注:Wire
Wesley13 Wesley13
3年前
TCP是如何实现三次握手的?
什么是三次握手1.TCP是网络传输层的协议,提供面向连接的可靠的字节流服务,要通信得先建立连接2.所谓三次握手就是指,建立一个TCP连接时,需要CLient与Server发送三个包,确认连接的建立3.这一过程由Client执行connect触发简单描述下三次握手的具体过程第一
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这