TCP协议全称为:Transmission Control Protocol,是一种面向链接、保证数据传输安全、可靠的数据传输协议。为了确保数据的可靠传输,不仅需要对发出的每个字节进行编号确认,还需要验证每一个数据包的有效性。每个TCP数据包是封闭在IP包中的,每个一IP包的后面紧跟着的是TCP头,TCP报文格式如下:

源端口和目的端口字段

  • TCP源端口(Source Port):源计算机上的应用程序的端口号,占 16 位。

  • TCP目的端口(Destination Port):目标计算机的应用程序端口号,占 16 位。

序列号字段

CP序列号(Sequence Number):占 32 位。它表示本报文段所发送数据的第一个字节的编号。在 TCP 连接中,所传送的字节流的每一个字节都会按顺序编号。当SYN标记不为1时,这是当前数据分段第一个字母的序列号;如果SYN的值是1时,这个字段的值就是初始序列值(ISN),用于对序列号进行同步。这时,第一个字节的序列号比这个字段的值大1,也就是ISN加1。

确认号字段

TCP 确认号(Acknowledgment Number,ACK Number):占 32 位。它表示接收方期望收到发送方下一个报文段的第一个字节数据的编号。其值是接收计算机即将接收到的下一个序列号,也就是下一个接收到的字节的序列号加1。

数据偏移字段

TCP 首部长度(Header Length):数据偏移是指数据段中的“数据”部分起始处距离 TCP 数据段起始处的字节偏移量,占 4 位。其实这里的“数据偏移”也是在确定 TCP 数据段头部分的长度,告诉接收端的应用程序,数据从何处开始。

保留字段

保留(Reserved):占 4 位。为 TCP 将来的发展预留空间,目前必须全部为 0。

标志位字段

  • CWR(Congestion Window Reduce):拥塞窗口减少标志,用来表明它接收到了设置 ECE 标志的 TCP 包。并且,发送方收到消息之后,通过减小发送窗口的大小来降低发送速率。

  • ECE(ECN Echo):用来在 TCP 三次握手时表明一个 TCP 端是具备 ECN 功能的。在数据传输过程中,它也用来表明接收到的 TCP 包的 IP 头部的 ECN 被设置为 11,即网络线路拥堵。

  • URG(Urgent):表示本报文段中发送的数据是否包含紧急数据。URG=1 时表示有紧急数据。当 URG=1 时,后面的紧急指针字段才有效。

  • ACK:表示前面的确认号字段是否有效。ACK=1 时表示有效。只有当 ACK=1 时,前面的确认号字段才有效。TCP 规定,连接建立后,ACK 必须为 1。

  • PSH(Push):告诉对方收到该报文段后是否立即把数据推送给上层。如果值为 1,表示应当立即把数据提交给上层,而不是缓存起来。

  • RST:表示是否重置连接。如果 RST=1,说明 TCP 连接出现了严重错误(如主机崩溃),必须释放连接,然后再重新建立连接。

  • SYN:在建立连接时使用,用来同步序号。当 SYN=1,ACK=0 时,表示这是一个请求建立连接的报文段;当 SYN=1,ACK=1 时,表示对方同意建立连接。SYN=1 时,说明这是一个请求建立连接或同意建立连接的报文。只有在前两次握手中 SYN 才为 1。

  • FIN:标记数据是否发送完毕。如果 FIN=1,表示数据已经发送完成,可以释放连接。

窗口大小字段

窗口大小(Window Size):占 16 位。它表示从 Ack Number 开始还可以接收多少字节的数据量,也表示当前接收端的接收窗口还有多少剩余空间。该字段可以用于 TCP 的流量控制。

TCP 校验和字段

校验位(TCP Checksum):占 16 位。它用于确认传输的数据是否有损坏。发送端基于数据内容校验生成一个数值,接收端根据接收的数据校验生成一个值。两个值必须相同,才能证明数据是有效的。如果两个值不同,则丢掉这个数据包。Checksum 是根据伪头 + TCP 头 + TCP 数据三部分进行计算的。

紧急指针字段

紧急指针(Urgent Pointer):仅当前面的 URG 控制位为 1 时才有意义。它指出本数据段中为紧急数据的字节数,占 16 位。当所有紧急数据处理完后,TCP 就会告诉应用程序恢复到正常操作。即使当前窗口大小为 0,也是可以发送紧急数据的,因为紧急数据无须缓存。

可选项字段

选项(Option):长度不定,但长度必须是 32bits 的整数倍。

TCP建立连接

TCP建立连接需要三个步骤,也就是大家熟知的三次握手。下图了正常情形下通过三次握手建立连接的过程:

  • A机器发出一个数据包SYN设置为1,表示希望建立连接。这个包中的假设seq为x

    • 机器A发送`SYN`数据包后,会进入`SYN_SENT`状态

  • B机器收到A发送的SYN数据后,响应一个数据包将SYNACK设置为1,假设这个响应包的序列号为y,同时期望下一次收到的数据库的序列为x+1

    • B回复响应包后,进入`SYN_RECD`状态

  • A收到B的响应包后,对响应包做应答将ACK标志设置为1,序列号为x + 1,期望下一次收到的数据包的序列号为y+1

    • A机器和B机器连接建立成功

TCP三次握手抓包验证

以为验证三次握手是否描述正确,在下使用Wireshark进行抓包验证。首先使用ping命令获取www.baidu.com的ip地址:

正在 Ping www.a.shifen.com [183.232.231.174] 具有 32 字节的数据:
来自 183.232.231.174 的回复: 字节=32 时间=16ms TTL=54
来自 183.232.231.174 的回复: 字节=32 时间=16ms TTL=54
来自 183.232.231.174 的回复: 字节=32 时间=16ms TTL=54183.232.231.172 的 Ping 统计信息:数据包: 已发送 = 3,已接收 = 3,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):最短 = 16ms,最长 = 16ms,平均 = 16ms

以上输出显示www.baidu.com的ip地址:183.232.231.174,然后使用Wireshark的过滤器仅显示与www.baidu.com通信的tcp数据包:

ip.src_host == "183.232.231.174" or ip.dst_host == "183.232.231.174" and tcp

使用Wireshark抓包分析后,验证TCP正常连接三次握手与上节描述的一致。

为什么是三次握手?

为什么是三次握手?三次握手主要有两个目的:信息对等防止超时

信息对等

两台机器通信时都需要确认四个信息:

  • 自己发报文的能力

  • 自己收报文的能力

  • 对方发报文的能力

  • 对方收报文的通知

第一次握手

第一次握手A机器向B机器发送SYN数据包,此时只有B机器能确认自己收报文的能力对方发报文的能力

一次握手完成B机器能够确认的信息有:

  • B机器收报文的能力

    A机器发报文的能力

第二次握手

每二次握手后B响应A机器的SYN数据包,此时A机器就能确认:自己发报文的能力自己收报文的能力对方发报文的能力对方收报文的能力

二次握手完成A机器能够确认的信息有:

  • A机器发报文的能力

    A机器收报文的能力

    B机器发报文的能力

    B机器收报文的能力

第三次握手

每三次握手后A应答B机器的SYN + ACK数据包,此时B机器就能确认:自己发报文的能力对方收报文的能力

三次握手完成B机器能够确认的信息有:

  • B机器发报文的能力

    A机器收报文的能力

至此经过三次握手A、B机器就能做到信息对等,双方都能确认自己和对方的收、发报文的能力,最后方便理解将信息对等制作成一个小表格:

防止超时

三次握手除了保证信息对等也是了防止请求超时导致脏连接。TTL网络报文的生存往往会超过TCP请求超时时间,如果两次握手就能创建连接,传输数据并释放连接后,第一个超时的连接请求才到达B机器,B机器 会以为是 A 创建新连接的请求,然后确认同意创建连接。因为A机器的状态不是SYN_SENT,所以会直接丢弃了B的确认数据,导致 B 机器单方面的创建连接完毕。

如果是三次握手,则 B 机器收到连接请求后,同样会向 A 机器确同意创建连接,但因为 A 不是SYN_SENT状态,所以 A机器 不会回复 B 机器确认创建连接请求,而 B 机器到一段时间后由于长时间没有收到确认信息,最终会导致连接创建失败,因此不会出现脏连接。

TCP断开连接

TCP是全双工通信,双方都能作为数据的发送方和接收方,但TCP会有断开的时候。TCP建立连接需要三次握手而断开连接却要四次,如图所示为TCP断开连接四次挥手过程:

  • A 机器发送关闭数据包将FIN设置为1,假设序列号为u,发完关闭数据包后此时 A 机器处理FIN_WAIT_1状态

  • B 收到关闭连接请求后,通知应用程序处理完剩下的数据

  • B 响应 A 的关闭连接请求,将ACK标志设置为1,seq为v,ack为u+1,随后 B 机器处于 CLOSE_WAIT状态

  • A 收到应答后,处于FIN_WAIT_2状态,继续等待 B 机器的FIN数据包

  • B 处理好现场后,主动向 A 机器发送数据包,并将FINACK标志设置为1,seq为w,ack为u+1,随后处于LAST_WAIT状态等待 A 机器的应答

  • A 机器收到FIN数据包后,随后发送ACK数据包,seq为u+1,ack为w+1, 此时 A 机器处理TIME_WAIT状态

  • B 机器收到ACK响应包后,进行CLOSED状态,连接正常关闭

  • A 机器在TIME_WAIT状态等待2MSL后,也进入CLOSEED状态,连接关闭

什么是2MSL:MSL是Maximum Segment Lifetime英文的缩写,中文可以译为“报文最大生存时间”,
2MSL即两倍的MSL

四次挥手断开连接可以用更形象的方式来表达:

  • 男生 :我们分手吧。

  • 女生 :好的,我需要去家里把东西收拾完,再发消息给你。(此时男生不能再拥抱女生)

  • 。。。,一个小时后

  • 女生 :我收拾完了,分手吧(此时女生也不能再拥抱男生)

  • 男生:好的(此时双方约定一段时间后,才可以分别找新的对象)

TCP四次挥手抓包验证

抓包过程与与三次握手抓包过程一致,这里不描述。直接看访问后抓包的截图:

  • 第一个包是由192.168.1.6这台机器(也就是客户机),发送了一个FIN包,seq为80,ack为2782

  • 第二个包由183.232.231.174(服务器),对192.168.1.6这台机器(也就是客户机)发送了一个ACK包,seq为2782,ack为81

  • 第三个包由183.232.231.174(服务器),对192.168.1.6这台机器(也就是客户机)发送了一个ACKFIN包,seq为2782,ack为81

  • 第四个包由192.168.1.6,向服务器响应了一个ACK包,seq为81,ack为2783

四次挥手流程与我们描述的一致。

TIME_WAIT 状态 

主动要求关闭的机器(机器A)表示收到对方的FIN报文后,并发送出ACK报文后,进行TIME_WAIT状态,等待2MSL后进行CLOSED状态。如果在TIME_WAIT_1 时收到FIN标志和ACK标志报文时,可以直接进入TIME_WAIT状态,而无需进入TIME_WAIT_2状态。

为什么要有 TIME_WAIT

确认被动关闭(机器B)能够顺利进入CLOSED状态

假如A机器发送最后一个ACK后,但由于网络原因ACK包未能到达 B 机器,此时 B机器通常会认为 A机器 没有收到 FIN+ACK报文,会重发一次FIN+ACK报文。如果 A机器 发送最后一个ACK后,自私的关闭连接进入 CLOSED状态,就可能导致 B 无法收到ACK报文,无法正常关闭。

防止失效请求

TIME_WAIT 状态可以防止已失效的请求包与正常连接的请求数据包混淆而发生异常。因为TIME_WAIT 状态无法真正释放句柄资源,在此期间, Socket中使用的本地端口在默认情况下不能再被使用。

CLOSE_WAIT 状态

被动关闭的机器(机器B)在收到对方发送的,FIN报文后,马上回复ACK报文,进入CLOSE_WAIT状态。通知应用程序,处理剩下的数据,释放资源。

特别推荐一个分享架构+算法的优质内容,还没关注的小伙伴,可以长按关注一下:

长按订阅更多精彩▼如有收获,点个在看,诚挚感谢

TCP 三次握手、四手挥手,这样说你能明白吧!相关推荐

  1. java锁一次交互二次握手_Java后台开发面试实战(二):TCP三次握手四次挥手

    感谢牛客网网友提供的面试经验! 1. 解释一下TCP三次握手四次挥手 图片来源于微信公众号:码农求职小助手 答: 嗯(稍作思考)- 三次握手简单来说,在数据传输开始前: 第一次握手:客户端向服务端发送 ...

  2. [计算机网络][总结][常见问题][TCP][三次握手][四次挥手]

    TCP三次握手 四次挥手 三次握手 目的:保证传输的可靠性,为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误.主要防止资源的浪费. 具体过程:当客户端发出第一个连接请求报文段时并没有丢 ...

  3. TCP三次握手四次挥手(图解)

    <TCP-IP协议栈概略图与TCP三次握手四次挥手> 目录 1 TCP过程详解 1.1 三次握手 1.2 四次挥手 2 使用tcpdump分析三次握手的过程 2.1 tcpdump抓包和t ...

  4. TCP三次握手四次挥手过程及其中的状态量

    网上看到过一些有关TCP三次握手四次挥手的过程,觉得有必要总结一下了,对于了解TCP的过程还是有帮助的 1.变量含义 SYN表示建立连接, FIN表示关闭连接, ACK表示响应, PSH表示有 DAT ...

  5. java 中的网络编程(Socket、TCP三次握手四次挥手、TCP/UDP/URL)

    文章目录 前言 一.网络编程概述 二.网络通信要素概述 1.如何实现网络中的主机互相通信 2.网络通信协议 3.IP和端口号 4.InetAddress类 5.网络协议 6.TCP/IP协议簇 7.T ...

  6. TCP三次握手四次挥手简介

    TCP三次握手四次挥手简介 图解三次握手.四次挥手 建立连接:三次握手 关闭连接:四次挥手 上图传递过程中出现的几个字符(SYN,ACK,FIN,seq,ack)各代表什么意思 SYN,ACK,FIN ...

  7. TCP三次握手四次挥手详解

    TCP三次握手四次挥手 1. TCP报文格式 2. TCP连接需要解决的问题 3. 三次握手 4. 四次挥手 5. 一些补充问题 1. TCP报文格式 在了解三次握手和四次挥手之前,先知道TCP报文内 ...

  8. TCP三次握手四次挥手 TCP/UDP区别

    三次握手 第一次握手: 建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认:  SYN:同步序列编号(Synchronize Sequence Numbe ...

  9. Wireshark验证TCP三次握手四次挥手

    本文介绍如何通过Wireshark抓包工具验证TCP的三次握手四次挥手过程. 首先本地起了一个tomcat服务器,跑了一个简单的基于SpringMVC的rest服务. 打开Wireshark,捕获指定 ...

  10. TCP三次握手四次挥手(三国版)

    TCP的三次握手四次挥手 TCP的三次握手和四次挥手不管是我们自己使用还是面试都是需要掌握的,本文先将原理,然后以三国为例讲个小栗子帮助理解.先来一张图: 标志位 TCP在其协议头中使用大量的标志位或 ...

最新文章

  1. 为了一个科研idea,博士生们连冥想、巫毒仪式都用上了
  2. [Android] DiffUtil在RecyclerView中的使用详解
  3. spring执行定时任务
  4. 编程技能和做员工的技能——哪个更重要?
  5. 周报(2017.3.19-3.16)
  6. java的运行原理_Java的运行原理(转载)
  7. c++多线程——同步并发
  8. doris历程_Doris简史-为分析而生的11年
  9. C#基础之--线程、任务和同步:一、异步委托
  10. Vue.js2.0从入门到放弃---入门实例(一)
  11. NWT失败反省:不想办法开展业务,天天想着让别人不能用
  12. 不变子空间与线性变换的矩阵之间的关系
  13. C语言关键字之inline
  14. 政考网:怎样考取公务员上岸?
  15. AOSP ~ 默认开启开发者模式
  16. 爬虫——Scrapy框架案例二:阳光问政平台
  17. 桌面壁纸 Lively wallpape
  18. csp 2022.6
  19. 上海市房管局:物业公司信用将能手机查询
  20. 第四次作业-微软必应词典客户端

热门文章

  1. Dos一键清理系统垃圾教程
  2. 学习Linux命令神器-看不懂直接给你解释
  3. 28岁适合转嵌入式开发吗?
  4. 安装旧版本插件_iOS 应用降级插件,支持任意版本升降
  5. golang 遍历list_golang如何把一个list遍历给一个切片
  6. 关于学习Python的一点学习总结(34->构造函数->重写方法和特殊构造)
  7. 关于TypeError: ‘numpy.ndarray‘ object is not callable报错
  8. 单调栈 or 线段树扫描线 ---- E. Delete a Segment [单调栈+二分] [扫描线处理空白位置的技巧乘2]
  9. python页面调用接口_python调用接口——requests模块
  10. linux yield_linux内核的一些知识点(上)