Table of Contents

  1. 前言
  2. 数据报头部
  3. 三次握手
    1. SYN 攻击
  4. 四次挥手
    1. 半连接
    2. TIME_WAIT
  5. 结语
  6. 参考链接

前言

TCP 中的三次握手和四次挥手应该是非常著名的两个问题了,一方面这两个过程基本上属于面试必考题目,另一方面,这两个过程在实际的使用中也非常重要。

这里就来简单的看一下这两个过程是怎么一回事吧。

数据报头部

在学习三次握手和四次挥手的具体过程之前,我觉得有必要先对 TCP/IP 的数据报头部进行一定的了解,当然,不需要了解所有信息。

上面的图片是 IP 数据报的头部结构,在这里,我们只需要明白:IP 数据报的头部会携带 源地址目的地址 的信息就足够了。

然后就是 TCP 数据报的头部结构:

TCP 头部的结构和 IP 头部一样,都比较复杂,但是在这里,我们也只需要关注其中的部分信息:

TCP 头部 作用或含义
源端口目的端口 和 IP 头部的 源地址目的地址 一起唯一地标识了每个连接
序列号 用来标识发送的字节流,即:发送的每个字节都是进行了编号的
确认号 确认发送方希望接下来接收到的数据报的序列号,即:确认收到了对方发送的前一个数据报
SYN 标志 建立新连接时该字段启用,表明本次发送的 序列号 为自身的 初始序列号
ACK 标志 表明 确认号 字段有效,连接建立以后一般都处于启用状态
FIN 标志 表明该报文的发送方已经结束向对方发送数据

三次握手

在对 TCP/IP 数据报的头部结构有了一定的了解后,就可以进入正题了,首先是三次握手的过程:

三次握手过程的文字描述:

  1. 第一次握手,客户端向服务端发送数据报,该数据报的 SYN 标志为 1,而序列号的值为 x
  2. 第二次握手,服务端向客户端发送数据报,该数据报的 SYN 标志和 ACK 标志为 1,而序列号的值为 y,确认号的值为 x + 1
  3. 第三次握手,客户端向服务端发送数据报,该数据报的 ACK 表示为 1,而序列号的值为 x + 1,确认号的值为 y + 1

这个过程其实不难,但是,更重要的是对这个过程的理解,或者说,就是需要明白:为什么要进行三次握手?

这个问题存在很多种解释,个人感觉最好的一个解释应该是 知乎 上的一个回答,这个回答从三次握手的目的出发对为什么需要三次握手进行了解释:

  1. 三次握手的目的除了让通信双方了解一个连接正在建立以外,还在于利用数据报的头部交换彼此的 初始序列号
  2. 当 SYN 标志位 1 时,会表明当前数据报头部的序列号就是 初始序列号
  3. 第一次握手时,客户端将自身的 初始序列号 发送给了服务端
  4. 第二次握手时,服务端通过确认号确认了客户端的 初始序列号
  5. 第二次握手时,服务端将自身的 初始序列号 发送给了客户端
  6. 第三次握手时,客户端通过确认号确认了服务端的 初始序列号

也就是说,三次握手的过程可以简化为客户端和服务端交换彼此的 初始序列号 的过程,每次交换需要:

  1. 发送 初始序列号 给另一方
  2. 接受到另一方的 确认号 表明 初始序列号 已经成功交给另一方

在这个过程中,由于单个数据报可以同时携带确认号、初始序列号,因此,将下面四个过程压缩成了三次握手:

  1. 客户端 -> 服务端:我的初始序列号为 X
  2. 服务端 -> 客户端:确认你的初始序列号为 X
  3. 服务端 -> 客户端:我的初始序列号为 Y
  4. 客户端 -> 服务端:确认你的初始序列号为 Y

可以看到,这个过程必然是需要三次握手的,少一次显得不够,多一次显得多余。

当然了,还有其他的一些解释,有兴趣的可以看一下参考链接中的文章。

SYN 攻击

SYN 攻击是针对三次握手过程的一种攻击方式,通过观察三次握手的过程可以发现,当服务端向客户端发送 SYN-ACK 后还未进入完整的连接状态,而是处于 半连接 状态。只有在接收到客户端的 ACK 后才会转入完整的连接状态。

而 SYN 攻击便是通过短时间内伪造大量不存在的 IP 地址,向服务器不断地发送 SYN 包实现的。这使得服务端存在大量未确认的半连接,这些半连接只有等待服务端不断的重发直至超时才会断开。

这些伪造的 SYN 包将长时间占用未连接队列,正常的 SYN 请求被丢弃,导致目标系统运行缓慢,严重者会引起网络堵塞甚至系统瘫痪。

四次挥手

四次挥手似乎没有三次握手那么有名,但也还是十分重要的一个过程,其具体过程如下:

四次挥手过程的文字描述:

  1. 第一次挥手,主动关闭者 A 向被动关闭者 B 发送 FIN 标志为 1 的数据报,并指明希望接收者看到的自己当前的序列号 u
  2. 第二次挥手,被动关闭者 B 将 u 值加一作为响应的确认号值,表明它已经成功接收到主动关闭者发送的 FIN
  3. 第三次挥手,被动关闭者 B 将身份转变为主动关闭者,并发送自己的 FIN,并指明希望接收者看到的自己当前的序列号 w
  4. 第四次挥手,A 将 w 值加一作为响应的确认号值,表明它已经成功接收到 B 发送的 FIN

和三次握手一样,我们需要的是对四次挥手过程的理解,这里就附上个人的理解好了:

  1. 四次挥手的过程其实就是关闭连接的过程
  2. 关闭连接的过程中,主动关闭者和被动关闭者需要停止各自的 发送接收 操作
  3. 任何一端只能主动关闭自身的 发送 操作
  4. 任何一端只能在确定对方已经停止 发送 操作以后才能停止相应的 接收 操作

也就是说,四次挥手的过程我们可以看成是客户端和服务端停止自身的 发送 操作并 通知 另一端的过程:

  1. 第一次挥手,主动关闭者通过发送带有 FIN 标志的数据报告诉被动关闭者:我的数据已经发送完了,你可以停止接受操作了
  2. 第二次挥手,被动关闭者通过发送带有相应确认号的数据报告诉主动关闭者:好的,你的通知我已受到,你可以停止发送操作了
  3. 第三次和第四次操作正好相反,原本的被动关闭者变为主动关闭者,关闭自身的 发送 操作并通知另一端

由于任何一端停止自身的 发送 操作并 通知 另一端都需要两次挥手的过程,因此,总的来说就需要四次挥手了。

半连接

通过对四次挥手过程的理解我们可以发现,连接的关闭过程是由两端分别停止自身的数据 发送 操作完成的,因此,假如一方停止发送操作,而另一方继续发送数据,这时便进入了半连接状态。

TIME_WAIT

TIME_WAIT 这个状态也是比较常见的一个问题了,第四次挥手后进行第四次挥手的一方会进入 TIME_WAIT 状态,要至少等待 2MSL 才关闭连接。

这是为了避免另一端没有收到自己的 ACK 又进行了 FIN 的重发,如果自己直接就把连接关了,那么就收不到这个 FIN 数据报了。这样一来,另一端就会长时间处在 LAST_ACK的状态。

虽然 TIME_WAIT 这个状态是出于好意,但有些时候还是为造成一些问题,特别是在 Web 服务器这种需要主动关闭连接的服务端。

2MSL 的时间长度默认情况下并不短,通常情况下可能有 30~300 秒,这意味着在这个时间段类相应的 端口 资源是一直被占据的,这对相当依赖有限的端口资源的服务器来说是难以接受的。

因此,可以考虑通过将 2MSL 调低来解决这样问题。

结语

说起来,学习计算机网络基础的时候,并没有怎么学习关于三次握手和四次挥手的内容,基本上都是简单的了解了一下就完事了。

直到面试遇到了这个问题 @_@

然后才发现,这里面的弯弯道道也还不少,而且,似乎离我们并不是那么远,也许,实际操作中的一些问题就是由这两个过程导致的。

所以说,这两个过程能称为面试问题中的常客也不是没有道理的,是真的很重要。

注:三次握手和四次挥手中还有一个比较重要的内容是状态的转换,这里基本上没有提及这方面的内容,有需要或有兴趣的可以查阅相关的资料。

参考链接

TCP 中的三次握手和四次挥手的更多相关文章

  1. 【极客思考】计算机网络:Wireshark抓包分析TCP中的三次握手与四次挥手

    [摘要]本文重点分析计算机网络中TCP协议中的握手和挥手的过程. [前提说明] 前段时间突然看到了一篇关于TCP/IP模型的文章,心想这段时间在家里也用wireshark抓了点包,那么想着想着就觉得需 ...

  2. TCP中的三次握手和四次挥手

    三次握手:目的是同步连接双方的序列号和确认号 并交换 TCP窗口大小信息. 理论上跟通话一样: a: 你听的到吗?  b: 我能听到.只需要两次就可以了,但建立连接阶段不是双向即时通信的,且最终的目的 ...

  3. TCP协议中的三次握手和四次挥手(图解)【转】

    建立TCP需要三次握手才能建立,而断开连接则需要四次握手.整个过程如下图所示: 先来看看如何建立连接的. [更新于2017.01.04 ]该部分内容配图有误,请大家见谅,正确的配图如下,错误配图也不删 ...

  4. TCP/IP协议三次握手和四次挥手大白话解说

    前言 昨天晚上被一位师傅问到了TCP/IP的工作机制,心里很清楚三次握手,然而对于四次挥手却忘了,这是大学习里学过的,奋而翻阅书籍和网络对之前所学的做一个温顾,算是夯实自我吧. TCP(Transmi ...

  5. 详解TCP连接的“三次握手”与“四次挥手”(下)

    上文链接: 详解TCP连接的"三次握手"与"四次挥手"(上) 四.TCP的四次挥手(Four-Way Wavehand) 0.前言 对于"三次握手&q ...

  6. 白话解说TCP/IP协议三次握手和四次挥手

    白话解说TCP/IP协议三次握手和四次挥手 1.背景 和女朋友异地恋一年多,为了保持感情我提议每天晚上视频聊天一次. 从好上开始,到现在,一年多也算坚持下来了. 1.1.问题 有时候聊天的过程中,我的 ...

  7. TCP为什么做三次握手、四次挥手

    TCP 为什么做三次握手.四次挥手? TCP 是为了解决可靠传输出现的.为了实现可靠性,TCP 做了流量控制.拥塞控制,并且在建立.关闭连接前做些机制:三次握手.四次挥手. 三次握手是为了让客户端.服 ...

  8. 真的懂了:TCP协议中的三次握手和四次挥手(关闭连接时, 当收到对方的FIN报文时, 仅仅表示对方不在发送数据了, 但是还能接收数据, 己方也未必全部数据都发送对方了。相当于一开始还没接上话不要紧,后来接上话以后得让人把话讲完)

    一.TCP报文格式 下面是TCP报文格式图: (1) 序号, Seq(Sequence number), 占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记. (2) 确 ...

  9. TCP/IP协议 三次握手与四次挥手

    一.TCP报文格式 TCP/IP协议的详细信息参看<TCP/IP协议详解>三卷本.下面是TCP报文格式图: 图1 TCP报文格式 上图中有几个字段需要重点介绍下:        (1)序号 ...

随机推荐

  1. 字典(dict),增删改查,嵌套

    一丶字典 dict 用{}来表示  键值对数据  {key:value}  唯一性 键 都必须是可哈希的 不可变的数据类型就可以当做字典中的键 值 没有任何限制 二丶字典的增删改查 1.增 dic[k ...

  2. div嵌套时,子元素设置margin-top失效问题

    这是因为父元素的padding设置为0时所产生的bug,它自动将margin-top提升到了父元素上,所以此时我们所设置的margin-top自动就到父元素上了,解决方案: 1.给父元素添加一个pad ...

  3. SQL数据库基础二

  4. Linux命令-4类

    一.系统管理与维护   1. pwd:print working directory    打印工作目录   2. cd:  change directory    改变或进入路径       ● c ...

  5. Git基础使用教程(仓库初始化,源码clone,源码push)

    一.下载Git源码管理客户端 Git下载地址:https://git-scm.com/ 二.检查电脑是否已安装Git 1)已安装:输入git出现下图提示则代表已安装成功. 2)未安装情况下git会出现 ...

  6. npm相关命令

    npm install npm install log4js npm list npm list log4js #查看模板安装版本 npm install log4js@1.0.1 #指定模块版本安装 ...

  7. ACM TOMM 2017最佳论文:让AI接手繁杂专业的图文排版设计工作

    编者按:你是否曾经为如何创作和编辑一篇图文并茂.排版精美的文章而烦恼?或是为缺乏艺术灵感和设计思路而痛苦?AI技术能否在艺术设计中帮助到我们?今天我们为大家介绍的这篇论文,“Automatic Gen ...

  8. (转载)WPF:DataGrid设置行、单元格的前景色

    WPF:DataGrid设置行.单元格的前景色 0. 说明 /********************************** 本示例实现功能1.DataGrid基本操作2.列标题样式3.内容居中 ...

  9. hihoCoder #1050 : 树中的最长路

    题意: 求出树上最长路径的长度,并返回. 思路: 刚看到数据<=10^5,假如是单分支的树,那么有5万层,就不能递归,那就用桟实现, 那就要将长度信息保存在另开的数组中,很麻烦!!这题专门给递归 ...

  10. UVA 11997 K Smallest Sums (多路归并)

    从包含k个整数的k个数组中各选一个求和,在所有的和中选最小的k个值. 思路是多路归并,对于两个长度为k的有序表按一定顺序选两个数字组成和,(B表已经有序)会形成n个有序表 A1+B1<=A1+B ...