1.前言

本文以博主在某次前端面试中被问到“什么是TCP协议中的三次握手和四次挥手?”为契机,经过整理教材、百度百科以及他人博客,再结合博主自身的理解,尽可能的以通俗易懂的语言来解释TCP协议中的三次握手和四次挥手的具体过程。

2.TCP连接和断开

客户端与服务端在建立TCP连接时需要经过三次握手才能建立,而断开连接则需要四次挥手。整个过程全览如下图所示:

我知道,直接看此图,相信大多数伙伴是懵逼的,下面我们就分别从建立连接和断开连接进行详细介绍。

3.“三次握手”建立连接

客户端与服务端在建立TCP连接时需要经过三次握手才能建立,其具体过程图解如下图:

上图中间的三个箭头即为三次握手。

官方说明(说也白说,还是不懂)

  • 第一次握手:建立连接时,客户端发送SYN包(SYN=j)到服务器,此时客户端进入SYN_SENT状态,并挂起等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。

  • 第二次握手:当服务器收到客户端发来的SYN包后,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

  • 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态。

至此完成三次握手。
怎么样,懵逼吧,我都说了,这种说明,说了也是白说!

博主说明(通俗易懂)

其实建立连接三次握手的过程跟我们平时打电话的过程是一样样的,我们来看这样一个场景:
某天,隔壁老王给隔壁老张打电话,有如下对话:
老王:天王盖地虎!
老张:天王盖地虎,小鸡炖蘑菇!
老王:小鸡炖蘑菇!
电话接通,老王和老张Blalalala....
下来我们结合上面三次握手的图解仔细分析下这个场景,

  • 首先,老王给老张打电话,老王就是客户端,老张就是服务端。只有老王给老张打了电话,老张才会去接电话,也就是说老张不会主动去找老王,只有老王找老张,老张才会应答老王。
    对应到上图中就是客户端主动打开,服务端在监听等待,只有当客户端主动发起建立连接请求的时候,服务端才会配合客户端进行连接。

  • 老王先说句“天王盖地虎!”,说完后老王等待老张回应,老王进入等待状态。
    这个过程对应于图中第一次握手客户端发送SYN包,发完客户端进入SYN_SENT状态。
  • 老张听到老王的话后,回复老王“天王盖地虎,小鸡炖蘑菇!”在这里有个问题,许多同学会认为老张听到老王的话后应该直接回复“小鸡炖蘑菇”就可以了呀,干嘛还要再把老王的话再说一遍。其实不然,老张之所以要重复老王说的那句“天王盖地虎”,是因为老张得清楚的表明我不但能听到你说话,而且我听的非常准确,你说的是“天王盖地虎”而没有被我听成是“上山打老虎”。
    这个过程就对应于图中第二次握手,当服务端收到客户端发来的SYN包后,服务端将SYN包并加上自己的ACK包一起发给客户端,告诉客户端,我不但能收到你发来的东西,我还收的很完整,没有丢包,不信我把刚收到你发来的包发给你看看。
  • 老王听到老张说的“天王盖地虎,小鸡炖蘑菇!”后,心想“嗯,老张能听到我说话,而且还听得很准确,我也得告诉老张我能听到他说话。”,随后,老王就把老张说的“小鸡炖蘑菇”再说给老张,表示告诉老张我也能听到你说话,而且我也听得很准确哦。
    这个过程就对应于图中第二次握手,当服务端收到客户端发来的SYN包后,服务端将SYN包并加上自己的ACK包一起发给客户端,告诉客户端,我不但能收到你发来的东西,我还收的很完整,没有丢包,不信我把刚收到你发来的包发给你看看。
  • 老王听到老张说的“天王盖地虎,小鸡炖蘑菇!”后,心想“嗯,老张能听到我说话,而且还听得很准确,我也得告诉老张我能听到他说话。”,随后,老王就把老张说的“小鸡炖蘑菇”再说给老张,表示告诉老张我也能听到你说话,而且我也听得很准确哦。
    这个过程就对应于图中的第三次握手,当客户端端收到服务端发来的SYN+ACK包后,客户端将ACK包再发给服务端,告诉服务端,我也能收到你发来的东西,我也收的很完整,没有丢包,不信我也把刚收到你发来的包发给你看看。
  • 当老张听到老王说的“小鸡炖蘑菇”后,老张心想“嗯,老王也能听到我说话”。如此,通过以上过程,老王和老张就知道对方能听到自己说话,接下来就可以Blalalala....

听完这么一分析,是不是豁然开朗!!!

那么问题来了

建立连接一定要握手三次吗?两次握手为什么不行?四次握手为什么不行?
还是以老王给老张打电话场景为例,


先看两次握手:
老王:老张,你能听到我说话吗?(第一次握手)
老张:我能听到,老王,你能听到我说话吗?(第二次握手)
此时,两次握手结束,按理连接已经建立成功,可是老张还不知道老王能不能听到自己说话,所以接下来
老王:我们今天去老刘家打麻将吧
老张:我能听到,老王,你能听到我说话吗?
老王卒。


再看四次握手:
老王:老张,你能听到我说话吗?(第一次握手)
老张:我能听到,老王,你能听到我说话吗?(第二次握手)
老王:我能听到,老张,你能听到我说话吗?(第三次握手)
老张:我能听到。(第四次握手)
老王和老张Blalalal....。

显然,两次握手根本就无法建立连接,而四次握手虽然可以建立连接,但是耗费资源啊

4.“四次挥手”断开连接

由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。断开流程如下图所示:

上图中间的四个箭头即为四次挥手。

官方说明

  • 当准备断开TCP连接时,客户端作为主动关闭方向服务端发送一个FIN,用来关闭客户端到服务端的数据传送,此时客户端进入FIN_WAIT1状态。
  • 服务端接收到这个FIN后,向客户端发回一个ACK确认包,此时服务端进入CLOSE_WAIT状态。
  • 客户端接收到服务端发回的ACK确认包后,进入FIN_WAIT1状态。
  • 服务端关闭与客户端的连接,并发送一个FIN给客户端,此时服务端进入LAST_ACK状态。
  • 客户端收到服务端发来的FIN包后,发回ACK报文确认,然后进入TIME_WAIT连接度断开状态,等2MSL后客户端即可回到CLOSED可用状态了。
  • 服务端接收到ACK后,便进入连接断开状态
    四次挥手只有官方说明没有博主说明,是因为博主还没有相当一个特别恰当的例子来比拟这个过程,等博主想到了再来补上

5.TCP通信十种状态

TCP从连接到断开总共要经历十种状态,如下图:

  1. LISTEN:表示服务端的处于连接监听状态,可以接受来自客户端的连接。
  2. SYN_SENT:这个状态与SYN_RCV相对应,当客户端SOCKET执行CONNECT连接时,它首先发送SYN报文,因此也随即它会进入到了SYN_SENT状态,并等待服务端的发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文。
  3. SYN_RCV:这个状态表示接受到了SYN报文,在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂。
  4. ESTABLISHED:客户端/服务端连接建立。
  5. FIN_WAIT_1:该状态是当客户端SOCKET在ESTABLISHED状态时,它想主动关闭连接,向服务端发送了FIN报文,此时该客户端SOCKET即进入到FIN_WAIT_1状态。
  6. CLOSE_WAIT:该状态的含义是表示服务端在等待关闭连接。当客户端关闭SOCKET后发送FIN报文给服务端,服务端毫无疑问地会回应一个ACK报文给客户端,此时服务端则进入到CLOSE_WAIT状态。
  7. FIN_WAIT_2:当客户端处于FIN_WAIT_1状态时,当收到服务端回应ACK报文后,则客户端会立即进入到FIN_WAIT_2状态。
  8. LAST_ACK:该状态是服务端在发送FIN报文后,最后等待客户端的ACK报文。当收到客户端的ACK报文后,也即可以进入到CLOSED可用状态了。
  9. TIME_WAIT:该状态表示客户端收到了服务端的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。
  10. CLOSED:这个状态没什么好说的了,表示连接关闭后回到初始状态。

具体流程

连接之前,服务端处于LISTEN(1)状态,当客户端向服务端发送连接请求SYN后,客户端处于SYN_SENT(2)状态,当服务端收到请求并发送回应SYN+ACK后,服务端处于SYN_RECV(3)状态,当客户端收到服务端的回应后,客户端处于已连接ESTABLISHED(4)状态,并向服务端发送ACK,最后服务端也处于已连接ESTABLISHED(4)状态
断开之前,当客户端向服务端发送断开请求FIN之后,客户端处于FIN_WAIT1(1)状态,服务端收到FIN之后,服务端处于CLOSE_WAIT(2)状态,服务端向客户端发送ACK回应,此时客户端处于FIN_WAIT2(3)状态,服务端也即变为LAST_ACK(4)状态,服务端向客户端发送FIN请求,客户端状态变为TIME_WAIT(5),最后,客户端向服务端回应ACK,客户端和服务端状态都变为CLOSED(6)。

6.结语

至此,TCP连接的三次握手和四次挥手全部总结完了,懂没懂就看个人理解了,反正我也是费了好大劲才理清其中的关系。

揭秘——TCP的三次握手和四次挥手的更多相关文章

  1. TCP的三次握手与四次挥手

    TCP的三次握手与四次挥手 一.TCP(Transmission Control Protocol 传输控制协议) TCP是面向对连接,可靠的进程到进程通信的协议 TCP是提供全双工服务,即数据可在同 ...

  2. 你应该这么理解TCP的三次握手和四次挥手

    前言: TCP协议是计算机的基础,他本身是一个非常非常复杂的协议. 本文只是蜻蜓点水,将从网络基础以及TCP的相关概念介绍开始,之后再将三次握手,四次挥手这些内容来阐述. 最后介绍一些常见问题,并给出 ...

  3. TCP/IP三次握手与四次挥手的正确姿势

    0.史上最容易理解的:TCP三次握手,四次挥手 https://cloud.tencent.com/developer/news/257281 A 理解TCP/IP三次握手与四次挥手的正确姿势http ...

  4. TCP的三次握手与四次挥手详解

    TCP的三次握手与四次挥手是TCP创建连接和关闭连接的核心流程,我们就从一个TCP结构图开始探究中的奥秘  序列号seq:占4个字节,用来标记数据段的顺序,TCP把连接中发送的所有数据字节都编上一个序 ...

  5. 【图解】给面试官解释TCP的三次握手与四次挥手-Web运用原理及网络基础

    作者 | Jeskson 来源 | 达达前端小酒馆 轻松了解HTTP协议 为什么要学习网络协议呢?为什么要学习计算机完了呢?显然这很重要,至少能够帮助你找到工作的原因之一,学习网络知识点太多太多,没有 ...

  6. TCP的三次握手与四次挥手笔记

    TCP的三次握手与四次挥手笔记 TCP Flags URG: 紧急指针标志 ACK:确认序号标志 PSH:push标志 RST:重置连接标志 SYN:同步序号,用于建立连接过程 FIN: finish ...

  7. TCP的三次握手与四次挥手理解及面试题

    TCP的三次握手与四次挥手理解及面试题(很全面) 转载自:https://blog.csdn.net/qq_38950316/article/details/81087809 本文经过借鉴书籍资料.他 ...

  8. TCP 的三次握手和四次挥手

    参考资料: 1.TCP的三次握手与四次挥手理解及面试题: 2.Http协议三次握手和四次挥手: 3.TCP通信的三次握手和四次撒手的详细流程(顿悟) 前置: 序号(也称序列号) - Sequence ...

  9. WireShark抓包分析以及对TCP/IP三次握手与四次挥手的分析

    WireShark抓包分析TCP/IP三次握手与四次挥手 Wireshark介绍: Wireshark(前称Ethereal)是一个网络封包分析软件.功能十分强大,是一个可以在多个操作系统平台上的开源 ...

随机推荐

  1. python-setup模块

    本地打包,setup安装 一.distutils 使用:distutils 进行打包,步骤如下,以单一文件为例. 1.创建文件 在同一目录下.写一个foo.py文件: #-*- coding:utf- ...

  2. ubuntu14.04 安装tensorflow始末

    基于ubuntu14.04 干净的系统一步步遇到的坑记录下来: 怀着平静学习的心情,问题总的能解决的! 1. 首先看了下当前python版本 python --version Python 2.7.6 ...

  3. C--二分搜索

    //二分搜索 //时间复杂度小 log2 n int search(int key, int a[], int len) { ; ; ; int mid; while(left<right) { ...

  4. Vue中音乐播放器

    一.安装依赖 yarn add vue-aplayer ​ or` npm i vue-aplayer 二.使用 <template> <div class="vue_ap ...

  5. Fiddler的安装

    相关下载软件(链接:https://pan.baidu.com/s/1HFdFNph6FGHOFtZq09ldpg 提取码:3u3l ) fiddler是基于.net环境的,所以需要先安装.net 安 ...

  6. 渗透测试-基于白名单执行payload--Forfiles

    0x01 Forfiles简介: Forfiles为Windows默认安装的文件操作搜索工具之一,可根据日期,后缀名,修改日期为条件.常与批处理配合使用. 微软官方文档:https://docs.mi ...

  7. Cocos2d-x 学习笔记(15.2) EventDispatcher 事件分发机制 dispatchEvent(event)

    1. 事件分发方法 EventDispatcher::dispatchEvent(Event* event) 首先通过_isEnabled标志判断事件分发是否启用. 执行 updateDirtyFla ...

  8. vue-cli3 关闭一直运行的 /sockjs-node/info?t= ...

    首先 sockjs-node 是一个JavaScript库,提供跨浏览器JavaScript的API,创建了一个低延迟.全双工的浏览器和web服务器之间通信通道. 本地项目运行就会自动去访问:http ...

  9. ESP8266开发之旅 网络篇⑩ UDP服务

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  10. OptimalSolution(6)--栈和队列

    一.设计一个有getMin功能的栈 题目:实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作.pop.push.getMin操作的时间复杂度都是O(1). 思路:设计两个栈,一 ...