三次握手与四次挥手

OSI模型

OSI是Open System Interconnection的缩写,意为开放式系统互联。国际标准化组织(ISO)制定了OSI模型,该模型定义了不同计算机互联的标准,是设计和描述计算机网络通信的基本框架。OSI模型把网络通信的工作分为7层,分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。 首先来看看OSI的七层模型:

https://user-gold-cdn.xitu.io/2018/2/10/1617ff96900f58a2?imageslim

我们需要简单的知道,数据从应用层发下来,会在每一层都会加上头部信息,进行 封装,然后再发送到数据接收端。这个基本的流程你需要知道,就是每个数据都会经过数据的封装和解封 装的过程。 在OSI七层模型中,每一层的作用和对应的协议如下:

https://user-gold-cdn.xitu.io/2018/2/10/1617ff9ee30a193d?imageslim

TCP报文

先来两个图,中英文对比下

上图中有几个字段需要重点介绍下:

序号:Seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。
确认序号:Ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,Ack=Seq+1。
标志位:共6个,即URG、ACK、PSH、RST、SYN、FIN等,具体含义如下:

  • URG(Urgent):紧急指针(urgent pointer)有效。
  • ACK(Acknowledgement ):确认序号有效。
  • PSH(Push):接收方应该尽快将这个报文交给应用层。
  • RST(Reset):重置连接。
  • SYN(Synchronous):发起一个新连接。
  • FIN(Finish):释放一个连接。

需要注意的是:

  1. 不要将确认序号Ack与标志位中的ACK搞混了。
  2. 确认方Ack=发起方Req+1,两端配对。

概述

通常情况下:一个正常的TCP连接,都会有三个阶段:

  1. TCP三次握手;
  2. 数据传送;
  3. TCP四次挥手

如图所示,给出了TCP通信过程的示意图。

 

三次握手

所谓三次握手(Three-way Handshake),是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。

第一次握手:

客户端发送TCP 连接请求报文段(其中SYN标志位置1,Sequence Number为x)

发送后,客户端进入SYN_SEND状态,开始等待来自服务器的确认;

该报文段,指明了客户端即将需要连接的 服务器上的 具体端口、初始序号X(保存在包头的Sequence Number字段)

第二次握手:

服务器收到客户端的SYN报文段后,服务器进行应答:

  • 设置 SYN标志位=1
  • 设置 ACK标志位=x+1 即 Acknowledgment Number = (客户端的ISN)Sequence Number+1
  • 设置 seq=y 即 Sequence Number = y

服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)并发送给客户端,此时服务器进入SYN_RECV状态;

第三次握手.

客户端收到服务器的SYN+ACK报文段

  • 设置SYN标志位=0
  • 设置Acknowledgment Number = y+1
  • 设置seq=z
  • 向服务器发送该ACK报文段。

这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。

为什么需要三次握手,而不是两次?

既然总结了TCP的三次握手,那为什么非要三次呢?怎么觉得两次就可以完成了。那TCP为什么非要进行三次连接呢?在谢希仁的《计算机网络》中是这样说的:

为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。

在书中同时举了一个例子,如下:

已失效的连接请求报文段”的产生在这样一种情况下:

因为:A发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达B。

所以:因为已经过了有效时间,所以这是一个已失效的报文段。

然而:B收到此失效的连接请求报文段后,就误认为是A再次发出的一个新的连接请求。于是就向A发出确认报文段,同意建立连接。假设采用“两次握手”,那么只要B发出确认,就已经进行了两次连接,所以新的连接就建立了。

但是:但是由于现在A并没有发出建立连接的请求(因为那个请求是以前发的,现在A甚至都可能关机了),所以不会理睬B的确认,也不会向B发送数据。但已经进行了“两次握手”,所以B以为新的运输连接已经建立,并一直等待A发来数据。

结果:B的连接已经建立,一直在等待A的消息,但A根本不在。这样就造成了资源的浪费。

而采用“三次握手”的办法可以防止上述现象发生。例如在刚才的情况下,假如采用“三次握手”的话,A就不会向B的确认发出确认,B由于收不到确认,就不会建立连接。

这就很明白了,防止了服务器端的一直等待而浪费资源。

引用知乎上的别人引用的一个回答,从另外一个角度阐释:

在Google Groups的TopLanguage中看到一帖讨论TCP“三次握手”觉得很有意思。贴主提出“TCP建立连接为什么是三次握手?”的问题,在众多回复中,有一条回复写道:“这个问题的本质是, 信道不可靠, 但是通信双发需要就某个问题达成一致. 而要解决这个问题, 无论你在消息中包含什么信息, 三次通信是理论上的最小值. 所以三次握手不是TCP本身的要求, 而是为了满足"在不可靠信道上可靠地传输信息"这一需求所导致的. 请注意这里的本质需求,信道不可靠, 数据传输要可靠. 三次达到了, 那后面你想接着握手也好, 发数据也好, 跟进行可靠信息传输的需求就没关系了. 因此,如果信道是可靠的, 即无论什么时候发出消息, 对方一定能收到, 或者你不关心是否要保证对方收到你的消息, 那就能像UDP那样直接发送消息就可以了.”。这可视为对“三次握手”目的的另一种解答思路。

举个例子

拿寄快递举个例子

三次握手的情况

  1. 你:你发微信给快递小哥,“快递小哥在吗?我要寄快递,可以来我家取快递吗?”
  2. 快递小哥:收到,你在家吗?在家我就去
  3. 你:在家,你来吧

结果:OK,然后快递小哥来拿快递

为什么要三次,我平时聊微信都是两次就开始聊了?

  1. 你:快递小哥在吗?来拿快递
  2. 快递小哥:好的,这就去

这两次连接不就建立了?没啥问题啊?为啥非要三次呢?

因为有异常情况

两次握手

1.你:快递小哥在吗?来我家拿快递

但是这时候,由于某种原因(比如网络延迟),消息没有及时到达,第二天消息才送达

2.快递小哥(第二天):收到了,我这就去

结果:连接建立成功,但是你并不在家,然后快递小哥一直在等你,没办法拿到你要寄的快递,造成了资源的浪费。

为了避免这种意外情况,所以要采用“三次握手”。

三次握手

  1. 你:快递小哥在吗?来我家拿快递
  2. 快递小哥(第二天):收到,你在家吗?在家我就去
  3. 你(第二天):没有回应

结果:快递小哥没有收到你的确认,所以连接建立失败,避免了资源的浪费。

为什么不是四次或者以上?

三次可以,为什么还多加几次???不怕资源浪费?家里有矿?

四次挥手

TCP的连接的拆除需要发送四个包,因此称为四次挥手(four-way handshake)。客户端或服务器均可主动发起挥手动作,在socket编程中,任何一方执行close()操作即可产生挥手操作。

https://i-blog.csdnimg.cn/blog_migrate/ddb6ccc98cdd3a4c4f0aca7258e94f59.webp?x-image-process=image/format,png

第一次挥手

因此当主动方发送断开连接的请求(即FIN报文)给被动方时,仅仅代表主动方不会再发送数据报文了,但主动方仍可以接收数据报文。

第二次挥手

被动方此时有可能还有相应的数据报文需要发送,因此需要先发送ACK报文,告知主动方“我知道你想断开连接的请求了”。这样主动方就不会因为没有收到应答而重复发送断开连接的请求。

第三次挥手

被动方在处理完数据报文后,便发送给主动方FIN报文;这样可以保证数据通信正常可靠地完成。发送完FIN报文后,被动方进入LAST_ACK阶段(超时等待)。

第四挥手

主动方发送ACK报文进行连接中断的确认,被动方接收后,连接就正式中断了。

建立连接只需要三次,取消连接为什么要四次?

对比 TCP 建立连接的时候,区别大概就是第二步拆成了两步。“三次握手”的时候确认 ACK 和同步 SYN 是一块返回的,断开连接则是分开发送,先发送 ACK 确认,再发送 FIN。这里主要是因为 B 端是被动断开的一方,A 发送完数据了,发送 FIN 表示我已经完事了,但是 B 不一定,可能还有数据会发送给 A。所以 B 会先 ACK 确认,然后当它真的没有数据要发送了,才会执行 FIN。

这种情况主要是由于 TCP 全双工传输的特性决定的。什么是全双工?也就是说连接是双向的,所以连接的取消也是两者都取消才算真的取消。所以 TCP 的数据传输也是这样,两端同时可以向对方发送数据,所以当 A 要断开连接的时候,B 接收到 FIN 表示没有数据会发来了,但是B可能还有数据需要发送,为了数据不丢失,即采用先确定后断开的方式。

举个例子

要取消连接

假如说三次:

  1. A:我要结束连接。
  2. B:等等啊,我还有数据要传给你
  3. A:没办法,我只有三次握手,告辞

结果:

在第二步,B有可能还有数据要传给A,但是A直接就结束了,造成了数据的丢失。

四次

1.A:我要结束连接

2.B:好的,我知道了。我还有点数据要传给你

(B对A传数据·····)

3.B:数据传完了,你可以结束了,我也要结束

4.A:OK,大家都结束了,拜拜

结果:两者连接都结束了,连接真的结束了。

 

参考:

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

https://juejin.im/entry/59ed5ec95188255b5560c8af

http://matt33.com/2016/08/30/http-protocol/

https://www.jianshu.com/p/9968b16b607e

https://www.jianshu.com/p/5e3601bdee2a

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值