TCP 的三次握手和四次挥手,可以说是老生常谈的经典问题了,通常也作为各大公司常见的面试考题,具有一定的水平区分度。看似是简单的面试问题,如果你的回答不符合面试官期待的水准,有可能就直接凉凉了。

本文会围绕,三次握手和四次挥手相关的一些列核心问题,分享如何更准确的回答和应对常见的面试问题,以后面对再刁钻的面试官,你都可以随意地跟他扯皮了。

面试TCP的意义

我想要先说明一个重要问题,到底面试 TCP 的意义何在?

经常会听到这样抱怨:我是做业务程序开发的,面试官竟然问我 TCP 三次握手、TCP 拥塞控制的问题,还问的这么细致?

这些同学会觉着面试官是闲的淡疼,或是故意刁难候选人,更有同学认为面试官是为了防止自己技术退步拿来练手的,这种想法我也是醉了。

当然,不同人对此可能会有不同的想法,但我们技术人应该以积极的心态来理解和面对这个问题,在我看来面试 TCP 有重要的意义:

1. 从面试官的角度,可以快速考察候选人对基础知识的掌握程度,以及候选人对待技术的那种知其所以然的态度。

2. 从求职者的角度,即使工作内容中没有直接用到 TCP 协议,但在遇到网络故障,调试和分析问题时,熟悉 TCP 显得十分重要,要不抓包都看不懂。

3. 从学习的角度,我们可以学习 TCP 的设计理念,比如 TCP 重传、拥塞控制,以及如何在性能和原理之间做权衡和取舍的,举一反三,将这些原理细节应用到我们平时的软件设计上,也是一种思维上的学习成长。

4. 如果想要调整 TCP 参数来提升传输速度,可服务器上相关的系统参数有几十个,究竟该怎么调整呢?

5. 在服务器本地的 TCP 连接状态出现了类似 fin_waittime_wait,该怎么解决,是什么原因引起的?如果不懂 TCP,即使别人告诉你解决方案,你也不能够真正理解的。

所以,我们非常有必要认真学习 TCP 协议,对 TCP 熟悉程度,在某种意义上也是你与别人拉开距离的重要标识。

TCP 基础

这里先帮小伙伴们熟悉和回顾下 TCP 的基本概念,以至于能够更好的理解文章后边的内容。

TCP 其实是非常复杂的协议,我们先聊一些基础的。我们知道 TCP 是一种可靠的协议,它主要通过解决这几个问题来实现可靠性的,分别是:乱序、丢包重传、流控、拥塞控制。通过从图中报文格式的字段,也能够简单了解到 TCP 的相关概念。

  • TCP 在网络 OSI 七层模型中的第四层,TCP 包是没有 IP 地址的,但有源端口和目的端口,用来标识通信的进程。
  • Sequence Number 是记录包的序号,TCP 会按照报文字节进行编号,它是用来解决包在网络中乱序的问题。
  • Acknowledgement Number 确认序列号,是用于向发送方确认已经收到了哪些包,用来解决不丢包的问题。
  • Windows 也叫 Advertised-Windows,也就是著名的滑动窗口,主要是用来解决流控的。
  • TCP Flag 就是包的类型,主要是用于操控 TCP 状态机的。

三次握手

三次握手是各个公司常见的面试考点。以过来人经验来讲,虽然该问题看似简单,但你还真不一定能够回答的好。

见过比较典型面试问答场景:

面试官:请描述一下三次握手的过程吧

求职者:第一次客户端给服务端发送一个报文,第二次是服务器收到包之后,也给客户端应答一个报文,第三次是客户端再给服务器发送一个回复报文,TCP 三次握手成功。

面试官:还有吗?

求职者:说完了哈,这就是三次握手,很简单的

面试官:嗯,我没什么问的了,你还有什么问题吗?

这时求职者紧张的心终于平静了,因为面试官没有深入下去的意思,继续问下去可能也不懂,皆大欢喜!当然本次面试基本上也就 game over了。

求职者回答的不正确么?正确,但是回答的过于简单,离面试官的期望的答案还有一定的距离,我们该怎么回答呢?

TCP 三次握手,其实就是建立一个 TCP 连接,客户端与服务器交互需要 3 个数据包。握手的主要作用就是为了确认双方的接收和发送能力是否正常,初始序列号,交换窗口大小以及 MSS 等信息。

  • 第一次握手:客户端发送 SYN 报文,并进入 SYN_SENT 状态,等待服务器的确认;
  • 第二次握手:服务器收到 SYN 报文,需要给客户端发送 ACK 确认报文,同时服务器也要向客户端发送一个 SYN 报文,所以也就是向客户端发送 SYN + ACK 报文,此时服务器进入 SYN_RCVD 状态;
  • 第三次握手:客户端收到 SYN + ACK 报文,向服务器发送确认包,客户端进入 ESTABLISHED 状态。待服务器收到客户端发送的 ACK 包也会进入 ESTABLISHED 状态,完成三次握手。

我们回答时,可以先简单概述 TCP 过程,然后三次握手具体描述时,需要说明状态的基本转换。

TCP 三次握手,其实就是 TCP 应用在发送数据前,通过 TCP 协议跟通信对方协商好连接信息,建立起TCP的连接关系。

我们需要知道,TCP 连接并非是在通信设备两端之间建立信号隧道,而本质上就是双方各自维护所需的状态状态,以达到 TCP 连接的效果。所以 TCP 状态机是 TCP 的核心内容,学习 TCP 一定要搞懂这些状态机之间的转换。

二次握手可以吗

问:为什么 TCP 采用三次握手,二次握手可以吗?

我们可以从几个方面来解释:

(一)确认双方的收发能力

TCP 建立连接之前,需要确认客户端与服务器双方的收包和发包的能力。

1. 第一次握手:客户端发送网络包,服务端收到了。这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。

2. 第二次握手:服务端发包,客户端收到了。这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。不过此时服务器并不能确认客户端的接收能力是否正常。

3. 第三次握手:客户端发包,服务端收到了。这样服务端就能得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常。

所以,只有三次握手才能确认双方的接收与发送能力是否正常。

(二)序列号可靠同步

如果是两次握手,服务端无法确定客户端是否已经接收到了自己发送的初始序列号,如果第二次握手报文丢失,那么客户端就无法知道服务端的初始序列号,那 TCP 的可靠性就无从谈起。

(三)阻止重复历史连接的初始化

客户端由于某种原因发送了两个不同序号的 SYN 包,我们知道网络环境是复杂的,旧的数据包有可能先到达服务器。如果是两次握手,服务器收到旧的 SYN 就会立刻建立连接,那么会造成网络异常。

如果是三次握手,服务器需要回复 SYN+ACK 包,客户端会对比应答的序号,如果发现是旧的报文,就会给服务器发 RST 报文,直到正常的 SYN 到达服务器后才正常建立连接。

所以三次握手才有足够的上下文信息来判断当前连接是否是历史连接。

(四)安全问题

我们知道 TCP 新建连接时,内核会为连接分配一系列的内存资源,如果采用两次握手,就建立连接,那会放大 DDOS 攻击的。

TCP 作为一种可靠传输控制协议,其核心思想:既要保证数据可靠传输,又要提高传输的效率,而三次握手恰好可以满足以上两方面的需求!

初始序列号(ISN)

问:ISN 代表什么?意义何在?ISN 是固定不变的吗?ISN为何要动态随机?

ISN 是什么?

答:ISN 全称是 Initial Sequence Number,是 TCP 发送方的字节数据编号的原点,告诉对方我要开始发送数据的初始化序列号

ISN 是固定不变的吗?

答:ISN 如果是固定的,攻击者很容易猜出后续的确认序号,为了安全起见,避免被第三方猜到从而发送伪造的 RST 报文,因此 ISN 是动态生成的

半连接队列

什么是半连接队列?

答:服务器第一次收到客户端的 SYN 之后,就会处于 SYN_RCVD 状态,此时双方还没有完全建立连接。服务器会把这种状态下请求连接放在一个队列里,我们把这种队列称之为半连接队列。

当然还有一个全连接队列,就是已经完成三次握手,建立起连接的就会放在全连接队列中。如果队列满了就有可能会出现丢包现象。

三次握手可以携带数据吗?

问:三次握手过程中,可以携带数据吗?

答:第一次、第二次握手不可以携带数据,而第三次握手是可以携带数据的。

我们可以思考一个问题,假如第一次握手可以携带数据的话,如果有人要恶意攻击服务器,那他每次都在第一次握手中的 SYN 报文中放入大量的数据,疯狂着重复发 SYN 报文,这会让服务器花费大量的内存空间来缓存这些报文,这样服务器就更容易被攻击了。

对于第三次握手,此时客户端已经处于连接状态,他已经知道服务器的接收、发送能力是正常的了,所以可以携带数据是情理之中。

TCP 四次挥手

当我们的应用程序不需要数据通信了,就会发起断开 TCP 连接。建立一个连接需要三次握手,而终止一个连接需要经过四次挥手。

  • 第一次挥手。客户端发起 FIN 包(FIN = 1),客户端进入 FIN_WAIT_1 状态。TCP 规定,即使 FIN 包不携带数据,也要消耗一个序号。
  • 第二次挥手。服务器端收到 FIN 包,发出确认包 ACK(ack = u + 1),并带上自己的序号 seq=v,服务器端进入了 CLOSE_WAIT 状态。这个时候客户端已经没有数据要发送了,不过服务器端有数据发送的话,客户端依然需要接收。客户端接收到服务器端发送的 ACK 后,进入了 FIN_WAIT_2 状态。
  • 第三次挥手。服务器端数据发送完毕后,向客户端发送 FIN 包(seq=w ack=u+1),半连接状态下服务器可能又发送了一些数据,假设发送 seq 为 w。服务器此时进入了 LAST_ACK 状态。
  • 第四次挥手。客户端收到服务器的 FIN 包后,发出确认包(ACK=1,ack=w+1),此时客户端就进入了 TIME_WAIT 状态。注意此时 TCP 连接还没有释放,必须经过 2*MSL 后,才进入 CLOSED 状态。而服务器端收到客户端的确认包 ACK 后就进入了 CLOSED 状态,可以看出服务器端结束 TCP 连接的时间要比客户端早一些。

问:为什么建立连接握手三次,关闭连接时需要是四次呢?

答:其实在 TCP 握手的时候,接收端发送 SYN+ACK 的包是将一个 ACK 和一个 SYN 合并到一个包中,所以减少了一次包的发送,三次完成握手。

对于四次挥手,因为 TCP 是全双工通信,在主动关闭方发送 FIN 包后,接收端可能还要发送数据,不能立即关闭服务器端到客户端的数据通道,所以也就不能将服务器端的 FIN 包与对客户端的 ACK 包合并发送,只能先确认 ACK,然后服务器待无需发送数据时再发送 FIN 包,所以四次挥手时必须是四次数据包的交互。

问:为什么TIME_WAIT 状态需要经过 2MSL 才能返回到 CLOSE 状态?

答:MSL 指的是报文在网络中最大生存时间。在客户端发送对服务器端的 FIN 的确认包 ACK 后,这个 ACK 包是有可能不可达的,服务器端如果收不到 ACK 的话需要重新发送 FIN 包。

所以客户端发送 ACK 后需要留出 2MSL 时间(ACK 到达服务器 + 服务器发送 FIN 重传包,一来一回)等待确认服务器端确实收到了 ACK 包。

也就是说客户端如果等待 2MSL 时间也没有收到服务器端的重传包 FIN,说明可以确认服务器已经收到客户端发送的 ACK

还有第 2 个理由,避免新旧连接混淆。

在客户端发送完最后一个 ACK 报文段后,在经过 2MSL 时间,就可以使本连接持续的时间内所产生的所有报文都从网络中消失,使下一个新的连接中不会出现这种旧的连接请求报文。

你要知道,有些自作主张的路由器会缓存 IP 数据包,如果连接重用了,那么这些延迟收到的包就有可能会跟新连接混在一起。

总结

本篇文章以 TCP 三次握手和四次挥手这个经典问题为主题,初步窥探了 TCP 协议的入门知识点,后边会有一系列的文章,来分享 TCP 协议相关的方方面面,如果感兴趣请关注我,我们一起把 TCP 协议彻底搞透彻了。

最后,帮大家总结一下 TCP 的核心知识点。我们知道 TCP 协议是可靠的,它主要是通过解决如下几个问题来保证可靠性的:

  • 乱序
  • 丢包
  • 流控
  • 拥塞控制

TCP 是一个巨复杂的协议,基本上 TCP 涉及的所有内容都是围绕解决这几个问题的,请务必时刻认真牢记。

推荐阅读

阿里二面,面试官居然把 TCP 三次握手问的这么细致的更多相关文章

  1. 面试官:为什么 TCP 三次握手期间,客户端和服务端的初始化序列号要求不一样?

    大家好,我是小林. 为什么 TCP 三次握手期间,客户端和服务端的初始化序列号要求不一样的呢? 接下来,我一步一步给大家讲明白,我觉得应该有不少人会有类似的问题,所以今天在肝一篇! 正文 为什么 TC ...

  2. 面试官求你了,别再问我TCP的三次握手和四次挥手

    少点代码,多点头发 本文已经收录至我的GitHub,欢迎大家踊跃star 和 issues. https://github.com/midou-tech/articles 三次握手建立链接,四次挥手断 ...

  3. 面试官问我TCP三次握手和四次挥手,我真的是

    候选者:面试官你好,请问面试可以开始了吗 面试官:嗯,开始吧 面试官:今天来聊聊TCP吧,TCP的各个状态还有印象吗? 候选者:还有些许印象的,要不我就来简单说下TCP的三次握手和四次挥手的流程吧 候 ...

  4. 面试官:说说TCP和UDP的区别和应用场景

    原创文章首发于公众号:「码农富哥」,欢迎收藏和关注,如转载请注明出处! 上一篇聊完 一文彻底搞懂 TCP三次握手.四次挥手过程及原理 这次聊聊TCP和UDP的区别和场景 TCP/IP 中有两个具有代表 ...

  5. 反制面试官 | 14张原理图 | 再也不怕被问 volatile!

    反制面试官 | 14张原理图 | 再也不怕被问 volatile! 悟空 爱学习的程序猿,自主开发了Java学习平台.PMP刷题小程序.目前主修Java.多线程.SpringBoot.SpringCl ...

  6. 面试问题之计算机网络:TCP三次握手四次挥手

    转载于:https://www.cnblogs.com/Andya/p/7272462.html TCP三次握手: 起初A和B都处于CLOSED关闭状态 B创建TCB,处于LISTEN收听状态,等待A ...

  7. TCP三次握手那些事

    临近5月,春招和实习招聘逐渐进入尾声.本文主要讨论面试中经常提问的TCP连接的机制,附带一些扩展知识. 参加面试的时候,过半的面试官都会问TCP相关问题,而最常见的问题就是:讲一下TCP三次握手(四次 ...

  8. 浅谈浏览器解析 URL+DNS 域名解析+TCP 三次握手与四次挥手+浏览器渲染页面

    (1)浏览器解析 URL 为了能让我们的知识层面看起来更有深度,我们应该考虑下面两个问题了: 从浏览器输入 URL 到渲染成功的过程中,究竟发生了什么? 浏览器渲染过程中,发生了什么,是不是也有重绘与 ...

  9. 应聘复习基础笔记1:网络编程之TCP与UDP的优缺点,TCP三次握手、四次挥手、传输窗口控制、存在问题

    重要性:必考 一.TCP与UDP的优缺点 ①TCP---传输控制协议,提供的是面向连接.可靠的字节流服务.当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据.TCP提供 ...

随机推荐

  1. Taro 3.x in Action

    Taro 3.x in Action React, 小程序 https://taro-docs.jd.com/taro/docs/README Taro Next 跨端, 跨框架 Taro 是一个开放 ...

  2. 开放式 Web 应用程序安全性项目 OWASP

    开放式 Web 应用程序安全性项目 OWASP Open Web Application Security Project (OWASP) OWASP 基金会是谁? Open Web Applicat ...

  3. Chrome Enhanced Protection

    Chrome Enhanced Protection chrome://settings/security?q=enhanced 站内外链跳转拦截 refs xgqfrms 2012-2020 www ...

  4. toString()[0]

    toString()[0] https://prepack.io/ x = `A` //"A" x.toString()[0] //"A" x.toString ...

  5. nodejs package.json中的exports

    test/package.json { "name": "test", "main": "index.js", &quo ...

  6. React Styleguidist

    React Styleguidist https://www.thoughtworks.com/cn/radar/techniques/micro-frontends https://github.c ...

  7. 详解稳定币圣杯USDN

    稳定币飞速发展,USDN 一骑绝尘,但因合规问题饱受质疑.合规稳定币作为后来者,奋起直追,亦光耀夺目.而更符合区块链精神的稳定币(抵押其他资产生成稳定币),长期以来只有 Maker 的 DAI 能够在 ...

  8. C++算法代码——鹅卵石游戏

    题目来自:http://218.5.5.242:9018/JudgeOnline/problem.php?id=2334 题目描述 为了消磨时光,奶牛Bessie和她的朋友Elsie喜欢玩一种她们在农 ...

  9. SpringBoot2.1中添加过滤器配置

    1:构造一个实现 Filter 接口的过滤器,并在类上添加@component注释: notice1:若不添加,则需在spring中注入该bean,不然会报错. package com.dev.fil ...

  10. 你要是还学不会,请提刀来见 Typora+PicGo+Gitee + node.js 打造个人高效稳定优雅图床

    你要是还学不会,请提刀来见 Typora+PicGo+Gitee + node.js 打造个人高效稳定优雅图床 经过前面两弹的介绍,相信大家对图床都不陌生了吧, 但是小魔童觉得这样做法还是不方便,使用 ...