TCP的三次握手四次挥手,估计大家都听过。但是真的能把每一步说明白的人比较少。我还记得在之前面试的时候被面试官一顿问,然后一脸懵B... 都是大学没好好上课 ,这篇文章就跟大家讲讲到底这三握四挥是在搞什么飞机。

三次握手

握手是指的双方进行连接的操作。

三次握手(图片来自网络)

为什么是三次握手

确认通信能力

我们要明白,如果需要进行通信,首先需要保证的是双方都具有发信和收信能力。在不知双方能力状态下进行的通信都是无法保证可靠性和通信效率的。那么通信双方如何确认对方的通信能力呢?

  1. A请求B进行连接。(B已确认B的收信能力和A的发信能力)
  2. B返回ACK相应。(A已确认双方的收发能力)
  3. A返回ACK并建立连接。(B确认双方收发能力) 上面可以看到,至少是进行三次握手,才能确认双方能力。

防止产生脏数据连接

网络通信情况复杂,不可能保证每一消息都能正常到达其目的地。在TCP连接中,TTL的网络报文的生存时间一般都会比TCP的连接超时时间要长。这样就有可能出现一个问题。A在发送第一次连接请求时,可能网络拥塞,导致数据包未短时间内到达。到达超时时间后,A又发送了一次连接请求,这次正常进行连接。连接结束断开后,A的第一次连接请求到达B,B返回ack。如果是两次握手,A通过当前的状态,直接拒绝B的请求,但B会单方面认为连接已经建立,实际上并不是...

每一次握手到底是传输了什么?

想知道除了ip和端口号,每次传输的信息是什么,我们首先得知道TCP传输信息的结构。

TCP报文结构(图片来源于网络)

第一次握手

  • 首先会将TCP的header部分的控制位(上图的flags)中的SYN置为1。表示希望建立连接。
  • 还有一个重要的数据,seq,即序号。这个东西是干嘛用的呢?这个涉及到TCP安全性和可靠性,与ack即确认号紧密相关。TCP在传输数据时,如果数据比较大,会进行拆分操作,将大数据拆成一个个小的数据包。序号就是在这个时候用的。我们必须要知道这个包的顺序是什么,才能把真正的数据在服务端还原。seq的顺序并不是从0或者1开始的,而是一个随机值。因为如果序号从1开始,那么整个通信的过程非常容易被预测。正因为是随机的,所以对方不知道你的seq,所以我们需要在开始收发数据之前,将seq先发送给对方。序号的初始值的传递就是通过SYN=1的操作传递的。

客户端此时处于同步状态,即可以建立连接。服务端处于监听状态。

第二次握手

  • 标志位。因为已经收到了客户端的建立连接请求。所以必须要发送ack,以告知客户端自己已经收到消息。所以ACK的标志位要置为1,且SYN也是1,因为还未建立连接。
  • seq。同第一次握手一样,也是一个随机值(TCP为全双工,所以双方都需要保留seq方便处理数据包)。
  • ack。是对客户端发过来的序列号进行计算得到的

服务端处于SYN接收状态。

第三次握手

  • 标志位。此时只需要ACK=1。SYN已经不需要了,双方已经同步完seq等信息。
  • seq。可以说是第二次握手收到的ack。
  • ack。是对第二次握手收到的序列号进行计算得到的。用以告知已收到二次握手信息。

客户端处于连接建立状态,服务端收到信息之后也会进入连接建立状态,双方可以进行通信。

四次挥手

TCP连接在数据传输完成之后需要关闭,不然会一直占用系统资源。TCP的连接关闭需要四次通信才行,分手也是个麻烦事儿。

为什么四次才能断开连接呢?

分手这件事情,两边都说明白,分别断开即可。但是想要确认对方都要断开,那么一次两次是不够的。

四次挥手(图片来自网络)

我们还是拿A、B来举例。假设A要主动断开和B的连接。

  1. A发送断开请求。(需要等待B的回复,不然B未收到消息 就单方面的断开有点不负责任。超时重传)
  2. B收到请求并回复A。(B收到请求后,很伤心,但是没有办法,只能断开连接,但是B是被动的接收断开,所以需要通知其应用程序做关闭准备)
  3. B这边准备完了,通知A可以断开了。
  4. A回复B,我收到消息了,断开连接吧。

请求发送的信息是什么?

关闭连接抓包

关闭由哪方开始?

答案是哪边都可以,无论是客户端还是服务器端,都可以主动发起关闭请求。发起关闭请求的前提是数据发送完毕,不一定非得等待对方确认完成。

第一次挥手

假设客户端发起关闭请求。那么客户端发完消息后,会进入FIN_WAIT阶段。此处已经无法再发送应用程序消息,只能处理关闭相关信息。

第二次挥手

服务端收到第一次挥手消息后,返回收到消息的ack。服务端会进入CLOSE_WAIT阶段。这个阶段是等待关闭阶段,通知应用程序发送剩余数据,处理现场信息,关闭相应资源

第三次挥手

你应该有点好奇为什么第三次挥手和第二次挥手都是同一个服务。第二次主要是一个ack响应,第三次主要是一个服务端关闭通知消息。两者目的不同。等到三次挥手完毕,那么服务端会进入LAST_ACK状态,即等待最后客户端(主动发起关闭的一方)的ack确认。

第四次挥手

第四次挥手是主动发起关闭的一方A,对被动关闭一方B的FIN消息的确认。第四次信息发送完成后,A会进入TIME_WAIT阶段,而不是直接删除套接字。具体原因我们在下面讲。收到第四次挥手信息后,B会直接进行关闭操作。

为什么会有TIME_WAIT?

还是那句话,网络并不是一个理想世界,任何异常情况都有可能发生。为了保证TCP连接能够正常关闭,主动发起关闭方不能直接删除套接字,而是需要经过一段时间等待。这个时间一般是2MSL(Maxumun Segment Lifetime 最大报文生存时间)。原因如下

  • 确认被动关闭方能够正常进入关闭状态。假设B未收到A最后的一个ack,会再次发送FIN消息(第三次挥手),如果A已经CLOSE了,那么B就会一直重试发送。所以A必须要进行一段时间的等待。
  • 防止失效请求。假设A关闭了此次连接,又重新在原来的端口号上开启了新的连接。原来在网络上发送的一些包(已失效但未超过ttl)到来之后,无法进行区分是否是正常的包,导致数据混乱。

举个例子来证明没有TIME_WAIT的情况。

  1. A断开了,并且删除了套接字。
  2. B没有收到A的最后一次ack,导致FIN重发。
  3. A重新开启了新的套接字新的连接,但是这个套接字和之前删除的套接字拥有相同的端口号。
  4. B后来重发的FIN会错误的跑到新的套接字,导致A开始执行断开操作。

所以TIME_WAIT也是为了防止上面的误删除。

总结

在并发量很高的时候,熟悉TCP的原理和参数调优变得尤为重要。我们关注的不仅仅是几次握手、几次挥手,也应该关注一些细节,细节决定成败。更应该多问问为什么如此设计,能解决什么问题。

后续

后续主要是与大家分享讨论一下对TCP的滑动窗口机制和可靠性保障的理解。如果有时间,可以跟大家分享一下TCP的参数等配置相关内容。

一个分享Java后端知识的原创公众号

tcp 二次握手时延_一篇搞懂TCP的三次握手 四次挥手相关推荐

  1. tcp udp区别优缺点_一文搞懂TCP与UDP的区别

    一.TCP协议: 位于传输层, 提供可靠的字节流服务.所谓的字节流服务(Byte Stream Service) 是指, 为了方便传输, 将大块数据分割成以报文段(segment) 为单位的数据包进行 ...

  2. 一篇搞懂TCP、HTTP、Socket、Socket连接池

    上一篇:闲鱼面试官:Thread.sleep(0) 到底有什么用?我:有点懵~ 作者:数澜科技 链接:https://www.jianshu.com/p/e47a766e03da 前言:作为一名开发人 ...

  3. udp 使用connect优点_一文搞懂TCP和UDP的区别

    TCP(Transmission Control Protocol,传输控制协议)和UDP(User Data Protocol ,用户数据报协议)都属于TCP/IP协议簇.TCP/IP协议集包括了超 ...

  4. python文件打开模式rb表示只读模式打开文件_一篇搞懂python文件读写操作(r/r+/rb/w/w+/wb/a/a+/ab)...

    关于文件操作的几种常用方式,网上已有很多解说,内容很丰富,但也因此有些杂乱复杂.今天,我就以我个人的学习经验写一篇详细又易懂的总结文章,希望大家看完之后会有所收获. 一.各模式逐个分解 'r':只读. ...

  5. python中w和wb区别_一篇搞懂python文件讀寫操作(r/r+/rb/w/w+/wb/a/a+/ab)

    關於文件操作的幾種常用方式,網上已有很多解說,內容很豐富,但也因此有些雜亂復雜.今天,我就以我個人的學習經驗寫一篇詳細又易懂的總結文章,希望大家看完之后會有所收獲. 一.各模式逐個分解 'r':只讀. ...

  6. python中w和wb区别_一篇搞懂python文件读写操作(r/r+/rb/w/w+/wb/a/a+/ab)

    关于文件操作的几种常用方式,网上已有很多解说,内容很丰富,但也因此有些杂乱复杂.今天,我就以我个人的学习经验写一篇详细又易懂的总结文章,希望大家看完之后会有所收获. 一.各模式逐个分解 'r':只读. ...

  7. mysql在线主从复制_一篇搞懂MySQL 8.0 Clone技术在线搭建主从复制全过程

    墨墨导读:MySQL从8.0.17开始新增了克隆Clone技术,可以在线进行MySQL的本地克隆或远程克隆,从此搭建从库可以不再需要备份工具来实现了,本文分享Clone技术在线搭建主从复制全过程,希望 ...

  8. 3 万字 + 100 张图带你彻底搞懂 TCP 面试题(强烈建议收藏)

    大家好,我是小林,一个专为大家图解的工具人. 不管面试 Java .C/C++.Python 等开发岗位, TCP 的知识点可以说是必问的了. 任 TCP 虐我千百遍,我仍待 TCP 如初恋. 过去不 ...

  9. C++ 一篇搞懂多态的实现原理

    C++ 一篇搞懂多态的实现原理 虚函数和多态 01 虚函数 在类的定义中,前面有 virtual 关键字的成员函数称为虚函数: virtual 关键字只用在类定义里的函数声明中,写函数体时不用. cl ...

最新文章

  1. javascript之window对象
  2. Android源码学习之工厂方法模式应用
  3. 为进大厂刷爆算法题,最后却倒在了基础题上?太苦了!
  4. 浅谈session,cookie,sessionStorage,localStorage的区别及应用场景
  5. 放弃Eclipse Juno
  6. Python之日志处理(logging模块)详解
  7. JSP HTTP 状态码
  8. python 组合优化 回撤最小_【策略回测】多因子搭配组合优化(内附bonus)
  9. Flume Event
  10. android多线程网络通信
  11. phpcms调用语句
  12. WIFI6 5G信道、频宽对应关系
  13. SL4A apk 编译生成
  14. python排列3彩票统计
  15. 驱动编程简单教程——PTC512(ADC芯片驱动)为例
  16. 机器人之Cartographer
  17. C++华为+阿里+鹅厂面经大盘点-如果换做你能成功吗?
  18. Mezzanine user 扩展
  19. Linux crash调试(一)
  20. 地震勘探 01:地震波001

热门文章

  1. C++函数的默认参数
  2. java 连接池技术_java数据库连接池技术原理(浅析)
  3. 75. CPU 100%运行实战案例分析
  4. fiddler filters 使用(fiddler只显示指定请求,fiddler不显示指定请求,即filter请求过滤)转自:http://blog.csdn.net/notejs/article/
  5. 01_Eclipse的使用方法
  6. 3线程同步:条件变量
  7. python字符串转变量名_python 如何把在字符串里面的名字变成变量,进行复制
  8. 深入浅出设计模式原则之依赖倒置原则
  9. PyTorch 实现 Mask-RCNN
  10. 批量选中删除(包含全选)---jsp,servlet