深入理解TCP三次握手与四次挥手过程以及抓包实验

这篇具有很好参考价值的文章主要介绍了深入理解TCP三次握手与四次挥手过程以及抓包实验。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、前言

最近,我正好在做socket相关的实验,发现现在对计算机网络知识有一点点模糊,借此机会,熟悉一下TCP连接过程并利用WireShark工具进行测试。

二、TCP报文首部

深入理解TCP三次握手与四次挥手过程以及抓包实验

  • 源端口号:占16比特,写入源端口号,用来 标识发送该TCP报文段的应用进程。
  • 目的端口号:占16比特,写入目的端口号,用来标识接收该TCP报文段的应用进程。
  • 序号(sequence number):Seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。表示这个包的数据部分的第一位应该在整个数据流中所在的位置。
  • 确认序号(acknowledge number):ack序号,占32位,只有ACK标志位(Acknowledgement)为1时,确认序号才有效,ack=seq+1。指出期望收到对方下一个TCP报文段的数据载荷的第一个字节的序号,同时也是对之前收到的所有数据的确认。若ack=n,则表明到序号n-1为止的所有数据都已正确接收,期望接收序号为n的数据。
  • 标志位:共6个,具体如下:
    • URG:占1比特,设置为1时,首部中的紧急指针有效。紧急指针占16比特,用来指明紧急数据的长度。
    • ACK(Acknowledgement):取值为1时确认号字段才有效;取值为0时确认号字段无效。
    • PSH:接收方的TCP收到该标志位为1的报文段会尽快上交应用进程,而不必等到接收缓存都填满后再向上交付。
    • RST:重置连接。RST为1时,表示TCP连接出现异常,需要断开。
    • SYN:SYN为1时,表示希望创建连接。
    • FIN:FIN为1时,表示希望断开连接。
  • 选项:一些可选信息,长度可变。
  • 填充:由于选项的长度可变,因此使用填充来 确保报文段首部能被4整除

注意

  1. 不要将确认序号ackACK标志位搞混。本文将大写ACK表示为标志位,小写ack表示为确认号
  2. 确认方ack=发送方seq+1
  3. SYN、FIN的传输虽然没有数据,但是会让下一次传输的seq增加一;但ACK的传输不会让下一次的传输seq加一(这里的下一次传输指的是同一个发送端的下一次传输)。

三、TCP三次握手

3.1、什么是三次握手

三次握手,是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。三次握手的目的是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号并交换 TCP 窗口大小信息。

注:TCP通过MSS字段来确保分段传输正常,而MSS是在三次握手中确认的。客户端与服务端会在【选项】字段中填写MSS大小,TCP协议会选择两者的最小值作为协商后的MSS大小。除此之外,时间戳也在【选项】字段中,也会在三次握手的时候交互。

3.2、TCP的连接建立要解决如下问题

  1. 使TCP双方能够确知对方的存在 。
  2. 使TCP双方能够协商一些参数( 最大窗口值是否使用窗口扩大选项和时间戳选项,以及服务质量等)。
  3. 使TCP双方能够对运输实体资源(例如缓存大小连接表中的项目等)进行分配。

3.3、三次握手过程

深入理解TCP三次握手与四次挥手过程以及抓包实验

解释

  1. 客户端向服务端发送连接请求报文段,此报文段首部中的同步位SYN被设置为1,表明这是一个tcp连接请求报文段。序号字段seq被设置了一个初始值x作为TCP客户进程所选择的初始序号。

    由于TCP连接建立是由TCP客户进程主动发起的,因此称为主动打开连接。

    请注意TCP规定SYN被设置为1的报文段不能携带数据但要消耗掉一个序号。

  2. 服务端收到客户端发来的连接请求报文,对该包进行确认后结束LISTEN阶段,并向客户端发送一段TCP报文,该报文段首部中的同步位SYN和确认位ACK 都设置为1,表明这是一个TCP连接请求。序号字段seq被设置了一个初始值y,作为服务器进程所选择的初始序号。确认号字段ack的值被设置成了x+1,这是对TCP客户进程所选择的初始序号seq的确认。随后服务器端进入SYN-RECV阶段。

    请注意这个报文段也不能携带数据,因为它是SYN被设置为1的报文段,但同样要消耗掉一个序号。

  3. 客户端接收到报文之后,此时客户端明白客户端到服务端的数据传输是正常的,因此结束SYN-SENT阶段,并向服务端发送报文段,该报文段首部中的确认位ACK被设置为1,表明这是一个普通的TCP确认报文段 。序号字段seq被设置为x+1,这是因为TCP客户进程发送的第一个TCP报文段的序号为x,并且不携带数据,因此第二个报文段的序号为x+1。确认号字段ack被设置为y + 1,这是对TCP服务器进程所选择的初始序号的确认,之后客户端进入ESTABLISHED状态。当服务器端收到来自客户端确认收到服务器数据的报文后,得知从服务器到客户端的数据传输是正常的,从而结束 SYN-RECV 阶段,进入 ESTABLISHED 阶段,从而完成三次握手

3.4、问题

3.4.1、建立TCP连接为什么需要三次握手?

首先,TCP是全双工通信的,这意味着客户端在给服务器端发送信息的同时,服务器端也可以给客户端发送信息。

三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的

我们将客户端与服务端理解为两个商量事情的人,如下是他们准备开始商量时的对话:

  1. 小王 ====> 小李 :我已经准备好开始讲了,我先从x处开始讲
  2. 小王 <==== 小李 :我收到了你要开始的消息,我现在已经确认好听你讲x+1处,同时,我先从y处开始讲。
  3. 小王 ====> 小李 :我收到了你要开始的消息,现在我已经确认好要听你讲y+1处。

注意,以上过程发生了4个事件:

  • 小王选择了”初始序列号x“,并将x告知给小李
  • 小李确认收到x
  • 小李选择了”初始序列号y“,并将y告知给小王
  • 小王确认收到y

那么,该次连接过程可以抽象为:

  1. 小王 ====> 小李 :我已经准备好开始讲了(SYN),我先从x处开始讲(SEQ=x)
  2. 小王 <==== 小李 :我收到了你要开始的消息(ACK),我现在已经确认好听你讲x+1处,同时,我也准备好了(SYN),我将从y处开始讲(SEQ=y)。
  3. 小王 ====> 小李 :我收到了你要开始的消息(ACK),现在我已经确认好要听你讲y+1处。

经过了过程1、2,小王可以确定他能发送和接收消息。

过程3之后,小李也明白了他也能发送和接收消息,此时,双方都确认发送与接收是可行的。

3.4.2、为什么TCP连接不是两次或者四次?

为什么不是两次?

因为两次握手只允许一方建立初始序列号,而另一方承认它。这意味着只有一方可以发送数据。

如果说是只选取三次握手前两次,那么服务端建立连接的请求就不会得到回应,此时服务端无法确定客户端是否接收到请求。

为什么不是四次?

四次握手是多余的,正如第一个问题的举例一样,发送ACK与SYN可以合并为一个包。

其实TCP连接需要两方都知道自己是否有接受和发送数据的能力, 第一次A发送消息,A,B都不知道自己是否有接受和发送能力, B收到A的消息后,B知道了我有接受消息的能力,B发送给A,A现在知道了我能接受消息,而且发送的消息B能接受到,也说明A有发送消息的能力,最后一次A给B发送信息,B也知道了我有发送消息的能力,至此,AB都有发送和接受消息的能力,所以是三次,刚刚好。

四、TCP四次挥手

4.1、什么是四次挥手

TCP 连接的释放需要发送四个包(执行四个步骤),因此称为四次挥手(Four-way handshake),客户端或服务端均可主动发起挥手动作。

4.2、四次挥手过程

此过程假设由客户端发起断开连接请求(通常也是如此)。

深入理解TCP三次握手与四次挥手过程以及抓包实验

解释

  1. 首先客户端向服务器发送一段 TCP 报文表明其想要释放 TCP 连接,其中:标记位 FIN设置为1,表示请求释放连接;序号为 Seq = u;随后客户端进入 FIN-WAIT-1 阶段,即半关闭阶段,并且停止向服务端发送通信数据。

  2. 服务器接收到客户端请求断开连接的 FIN 报文后,结束 ESTABLISHED 阶段,进入 CLOSE-WAIT 阶段并返回一段 TCP 报文,其中:标记位 ACK设置为1,表示接收到客户端释放连接的请求;序号为 Seq = v;确认号 ack = u + 1,表示是在收到客户端报文的基础上,将其序号值加 1 作为本段报文确认号ack 的值;随后服务器开始准备释放服务器端到客户端方向上的连接。客户端收到服务器发送过来的 TCP 报文后,确认服务器已经收到了客户端连接释放的请求,随后客户端结束 FIN-WAIT-1 阶段,进入 FIN-WAIT-2 阶段。

  3. 服务器端在发出 ACK 确认报文后,服务器端会将遗留的待传数据传送给客户端,待传输完成后即经过 CLOSE-WAIT 阶段,便做好了释放服务器端到客户端的连接准备,再次向客户端发出一段 TCP 报文, 其中:标记位 FINACK设置为1,表示已经准备好释放连接了;序号为 Seq = w;确认号 ack = u + 1,表示是在收到客户端报文的基础上,将其序号 Seq 的值加 1 作为本段报文确认号 ack 的值。随后服务器端结束 CLOSE-WAIT 阶段,进入 LAST-ACK 阶段。并且停止向客户端发送数据。

  4. 客户端收到从服务器发来的 TCP 报文,确认了服务器已经做好释放连接的准备,于是结束 FIN-WAIT-2 阶段,进入 TIME-WAIT 阶段,并向服务器发送一段报文,其中:标记位 ACK设置为1,表示接收到服务器准备好释放连接的信号;序号为 Seq= u + 1,表示是在已收到服务器报文的基础上,将其确认号 ack 值作为本段序号的值;确认号为 ack= w + 1,表示是在收到了服务器报文的基础上,将其序号 Seq 的值作为本段报文确认号的值。随后客户端开始在 TIME-WAIT 阶段等待 2 MSL。服务器端收到从客户端发出的 TCP 报文之后结束LAST-ACK 阶段,进入 CLOSED 阶段。由此正式确认关闭服务器端到客户端方向上的连接。客户端等待完 2 MSL 之后,结束 TIME-WAIT 阶段,进入 CLOSED 阶段,由此完成「四次挥手」。

    MSL:最大段生命周期(Maximum Segment Lifetime),

4.3、问题

4.3.1、为什么关闭连接需要四次挥手?

简单点说,因为需要两边都断开,但又需要在断开前确定两边都没有数据需要发送。

由于TCP属于全双工通信(即数据可在两个方向上同时传递),因此,每个方向都必须要单独进行关闭(单方向的关闭称之为半关闭)。当客户端发送FIN时,表明客户端已经没有数据需要发送,当客户端收到服务端传来的ACK时,说明此时客户端与服务端都已经明白客户端不再有数据发送。服务端同理,因此需要四次挥手。需要注意的是,服务端在收到客户端的FIN后,未必已经将所有数据发送给了客户端,不能立马发送FIN给客户端,因此第二次和第四次挥手最好不要合并,所以需要四次握手。

4.3.2、TCP 挥手可以只需要三次吗?

理论上可以。其实这与三次握手本质上可以认为是一样的。

因为服务器端收到客户端的FIN后,服务器端同时也要关闭连接,这样就可以把ACKFIN合并到一起发送(即将第二次挥手与第三次合并),节省了一个包,变成了“三次挥手”。但前提是要确保服务端已经没有数据要发送

4.3.3、为什么挥手时发送的报文FIN和ACK都为1,而不是只有FIN为1?

参考RFC793(tcp传输控制协议)第16页:

Acknowledgment Number: 32 bits

If the ACK control bit is set this field contains the value of the next sequence number the sender of the segment is expecting to receive.

Once a connection is established this is always sent.

如果设置了ACK控制位,则此字段包含该段发送方期望接收的下一个序列号的值。

一旦建立了连接,就会始终发送

这似乎是TCP协议的设计问题。因此,除了三次握手建立连接时,第一次发送的报文ACK标志不为1,其余的报文都为1。

4.3.4、四次挥手过程中,客户端为什么需要等待 2MSL,才进入 CLOSED 状态?

等待2MSL的主要目的

为了保证客户端发送的最后一个ACK报文段(第四次挥手)能够到达服务器端。

解释

因为客户端发送的最后一个ACK报文段有可能在网络中被丢弃,使得处于LASK—ACK状态的服务器端收不到对已发送的FIN+ACK报文段(第三次挥手)的确认,那么,此时服务器端会超时重传这个FIN+ACK报文段,而客户端就能在2MSL时间内收到这个重传的FIN+ACK报文段,接着客户端重传一次ACK确认报文,重新启动2MSL计时器,一切正常之后,客户端和服务端都进入到CLOSED状态。

如果客户端在TIME_WAIT状态不等待一段时间,而是在发送完ACK确认后立即释放连接,那么就无法收到服务端重传的FIN+ACK报文段,因而也不会再发送一次确认报文段,这样,服务端就无法正常进入CLOSED状态。

另一个目的

防止“已失效的连接请求报文段”出现在本连接中。

解释

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

为什么是2MSL?

MSL代表最大段生命周期,它是任何报文在网络上存在的最长时间,超过这个时间,报文将被丢弃,RFC793中规定MSL为2分钟。

简单地说,就是TIME_WAIT等待时间得保证大于等于2次报文的最大传输时间,而2MSL是能达到此要求的最小时间。

1 个 MSL 保证四次挥手中主动关闭方最后的 ACK 报文(第四次挥手)能最终到达对端
1 个 MSL 保证另一端没有收到 ACK 时,进行重传的 FIN 报文能够到达

三、实验

实验由Golang编写。

使用WireShark工具进行抓包。

服务端代码

func main() {
   listner, err := net.Listen("tcp", ":6666")
   if err != nil {
      log.Fatalln(err)
   }
   //最后关闭监听
   defer listner.Close()
   //建立连接
   conn, err := listner.Accept()
   if err != nil {
      log.Fatalln(err)
   }
   //最后关闭连接
   defer conn.Close()
   //读取数据
   buf := make([]byte, 512)
   n, err := conn.Read(buf)
   if err != nil {
      log.Fatalln(err)
   }
   fmt.Println(string(buf[:n]))
}

客户端代码

func main() {
   //发起连接
   dial, err := net.Dial("tcp", ":6666")
   if err != nil {
      log.Fatalln(err)
   }
   //最后关闭连接
   defer dial.Close()
   //写入数据并发送
   _, err = dial.Write([]byte("hello,world"))
   if err != nil {
      log.Fatalln(err)
   }
}

实验结果

注:6666端口为服务端,54022端口为客户端。

深入理解TCP三次握手与四次挥手过程以及抓包实验

说明:

  • 249~251是三次握手过程
  • 252~253是传输数据过程
  • 254~257是四次挥手过程

总结

TCP三次握手与四次挥手的本质原因还是因为TCP进行的是全双工通信。

真正理解TCP建立连接与释放连接还需要深入了解TCP各种机制,建议阅读一下《TCP/IP详解》。文章来源地址https://www.toymoban.com/news/detail-473527.html

参考

  • https://www.jianshu.com/p/15754b4e9458
  • https://juejin.cn/post/7028003193502040072
  • https://juejin.cn/post/7063829623024386056

到了这里,关于深入理解TCP三次握手与四次挥手过程以及抓包实验的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【三、接口协议与抓包】TCP的三次握手与四次挥手

    你好啊!我是山茶,一个持续探索 AI + 测试之路的程序员。 TCP协议是一种面向连接的、可靠的、基于字节流的传输层通信协议。常常被用于处理实时通信,因此,在传输效率上会稍逊色于UDP协议 报文结构 TCP协议的报文结构如下(图片源于网络,如果侵权,请联系我删除) 对于

    2024年03月14日
    浏览(63)
  • 什么是三次握手与四次挥手( 一篇文章讲清楚TCP协议与UDP协议)

        关于TCP协议和UDP协议大家应该都有所耳闻,我们常用的网络通讯。比如浏览网页、软件聊天、以及你看到的这篇文章,都是通过这两种协议来进行数据传输的。 到底他们是如何工作的?这两种协议的区别又是什么呢?请随武汉海翎光电的小编一起耐心看完这篇文章,你一

    2024年02月09日
    浏览(46)
  • linux【网络编程】TCP协议通信模拟实现、日志函数模拟、守护进程化、TCP协议通信流程、三次握手与四次挥手

    Tcp通信模拟实现与Udp通信模拟实现的区别不大,一个是面向字节流,一个是面向数据报;udp协议下拿到的数据可以直接发送,tcp协议下需要创建链接,用文件描述符完成数据的读写 1.1.1 接口认识 1.1.1.1 listen:监听socket 1.1.1.2 accept:获取连接 通信就用accept返回的文件描述符,

    2024年02月06日
    浏览(54)
  • TCP:三次握手 、四次挥手断开的过程

    还是大剑师兰特 :曾是美国某知名大学计算机专业研究生,现为航空航海领域高级前端工程师;CSDN知名博主,GIS领域优质创作者,深耕openlayers、leaflet、mapbox、cesium,canvas,webgl,echarts等技术开发,欢迎加底部微信(gis-dajianshi),一起交流。 No. 内容链接 1 Openlayers 【入门教

    2024年03月28日
    浏览(58)
  • TCP协议+三次握手/四次挥手过程(带图详解!!!)

    传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的通信协议,工作在 传输层 。 应用程序在使用 TCP 协议之前,必须先建立 TCP 连接。在传送数据完毕后,必须释放已经建立的 TCP 连接。 TCP运输连接主要有三个阶段: 建立TCP连接,也就是三

    2024年02月03日
    浏览(52)
  • 一文彻底搞懂 TCP三次握手、四次挥手过程及原理

    TCP 协议简述 TCP 提供面向有连接的通信传输,面向有连接是指在传送数据之前必须先建立连接,数据传送完成后要释放连接。 无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条连接。在TCP/IP协议中,TCP协议提供可靠的连接服务,连接是通过 三次握手 进行初始

    2024年02月04日
    浏览(39)
  • Wireshark数据包捕获与分析 观察三次握手与四次挥手

    本实验使用Wireshark抓取通信数据包。1)观察IP数据包的结构。2)观察TCP的三次握手与四次挥手过程。 预备知识:IP数据报结构、TCP数据报结构。 目录 原理 1. IP数据报结构 2. TCP数据报结构 3. TCP三次握手与四次挥手流程  步骤与结果 1. 使用Wireshark抓取ping命令的完整通信过程的

    2024年02月09日
    浏览(43)
  • 【计算机网络经典面试题】简述 TCP 三次握手和四次挥手的过程

    1)第一次握手:建立连接时,客户端向服务器发送SYN包(seq=x),请求建立连接,等待确认 2)第二次握手:服务端收到客户端的SYN包,回一个ACK包(ACK=x+1)确认收到,同时发送一个SYN包(seq=y)给客户端 3)第三次握手:客户端收到SYN+ACK包,再回一个ACK包(ACK=y+1)告诉服务

    2024年04月08日
    浏览(58)
  • 计算机网络—TCP和UDP、输入url之后显示主页过程、TCP三次握手和四次挥手

    TCP是面向连接的、可靠的,基于字节流的传输层通信协议 。 图片来源小林coding 序号:传输方向上字节流的字节编号。初始时序号会被设置一个随机的初始值(ISN),之后每次发送数据时,序号值 = ISN + 数据在整个字节流中的偏移。假设A - B且ISN = 1024,第一段数据512字节已经

    2024年02月14日
    浏览(49)
  • 深入协议栈了解TCP的三次握手、四次挥手、CLOSE-WAIT、TIME-WAIT。

            TCP网络编程的代码网上很多,这里就不再赘述,简单用一个图展示一下tcp网络编程的流程:                 这三个函数都是系统调用,我们可以分为请求连接方和被动连接两部分,我们知道请求连接方并非都是client,为了方便,本文用client代表主动连接方,s

    2024年02月09日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包