网络--tcp概述三次握手四次挥手粘包分包数据分段(代码片段)

小智RE0 小智RE0     2022-12-12     676

关键词:

文章目录


1. 初始概述


数据重传


要明白的一点:网络传输本身就是不可靠的;可能丢包或者数据重复.

案例:

客户端发送了3个数据包, 经过传输到达服务器端,但是只收到了3和1的包;

  • 数据包2丢包了
  • 发送和接收的次序出现问题, 客户端先发的数据包1,但服务器先收到的是数据包3;


网络中的路由节点较多,难免发生节点故障;数据包发送到网络中,使用了不同的网络链路,前后次序可能不一致.


(1)首先网络丢包难以避免,那么要保证不丢包就可用重发机制,服务器每次收到数据包,跟客户端确认,回复已收到. 若客户端在约定时间后还没有收到ACK确认编号,就认为是丢包了,重新发送数据包即可.
(2)但是如果每个数据包都得这样一个一个地确认,从效率上来看不可观.
那么就让客户端在发送数据包的时候,给每个数据包编号,由小到大排序递增,那么根据编号即可知道是哪个数据包.

比如服务器收到数据包1,2,3之后,回复给客户端ACK:3即可表示数据包1,2,3都收到了.


判断重复数据包


由于超过了通信双方约定的时间,客户端还没有收到服务器的确认,客户端就进行重复,但是此时服务器之前的确认收到ACK已经进入网络,准备在响应了,还没到客户端,此时服务器就可能收到重复数据.

那么就需要数据包判重,个已经收到的逐个比较,显然比较麻烦.
具体做法:采用顺序的ACK,比如服务器给客户端回复ACK:6,告知客户端所有小于等于6的数据包已经全部收到了,之后要再收到小于等于6的数据包,就说明重复,服务端丢弃该数据即可.


如何保证传输的顺序不乱


若服务器收到数据包1,2,3, 给客户端回复了ACK=3,然后收到了数据包5,6,7,但是4号数据包不见了,那么服务器就会把数据包5,6,7这三个先暂时存放,直到4号数据包发过来,然后给客户端回复ACK=7;
可是如果4号数据包一直不来, 那么等待到超时时间后,客户端重新发送数据包4,5,6,7,然后此时服务器收到数据包4之后,就回复ACK=7,对于数据包5,6,7判断去重丢弃即可.

服务器虽然是并发接收数据包,但数据包的ACK按照编号从小到大进行确认.
到最后的阶段,会通过消息顺序编号+客户端重复机制+服务器顺序ACK号,实现客户端到服务器的数据发送.


TCP的链接实际是逻辑层面的,当客户端与服务端交互时,其中的数据可能会走不同的网络链路;不过这个逻辑上的链接保证了数据的不重复性和有序性.


链接≈>状态机


  • 其中的而每一个TCP链接都采用4元组(客户端IP,客户端端口Port,服务器IP,服务器端口Port)来进行唯一确认. TCP的链接作为逻辑层面存在,那么就具有生命周期:创建连接–>传输数据–>关闭连接.
  • 每个连接作为状态机,客户端/服务端都得维护状态state.
  • (1)创建连接时,客户端/服务器处于关闭状态CLOSED.因为连接复用原则,所以每次都从最初的关闭状态开始.
  • (2)连接后双方达到通信状态:ESTABLSHED.
  • (3)使用完成后管理连接,通信双方回到关闭状态.

2. 三次握手 四次挥手


三次握手

最开始的时候客户端与服务端都处理关闭的CLOSED状态;
首先服务器启动进入到监听状态LISTEN,
客户端启动后发送SYN同步序列编号与 序列号seq=x; 进入同步已发送状态;
服务端监听接收到消息后,达到同步已收到状态, 且回复 SYN同步序列编号,ACK=x+1确认序列编号与序列号seq=y,
客户端收到回复后, 为服务端发出 确认序列编号ACK=y+1,
双方达到连接状态.

  • 这里的ACK = x+ 1 ,实际意思是:表示已经确认收到小于等于x序号的数据包,接下来需要x+1的数据包.
  • seq=y表示发送的数据包编号为y;TCP具有全双工特征; 这里就是 seq = yACK =x+1 一块发送出去了;即发送自己的数据包y,也回复确认自己收到了数据包x.


为什么是三次握手???

C : 服务器:我需要创建连接
S:OK
那么这样的两次握手,可靠吗? 服务器回复的OK,客户端是否可以成功接收到呢?服务器不确定.
而同样换为三次,四次握手,也无法搞定最后一次通信的ACK是否可以成功接收的问题.

这么一分析的话,2次,3次,4次都是这样的,但为什么TCP选择了3次握手呢?

三次握手就可以保证客户端与服务器对于自身的发送接收能力进行了认可;

  • (1)客户端发出数据包seq=x,客户端的发送能力已确认;
  • (2)服务端回复seq = y ACK = x+1,此时客户端确认自身的发送与接收能力, 服务端确认自己的接收能力;
  • (3)客户端发送ACK = y+1,服务器接收后,即可确认自己的发送能力.

且是否成功接收的问题,可以采用超时重传机制与心跳时间来控制.


网络两将军的问题:客户端向服务端发送一个http请求,例如客户端给数据库写入一个记录;超时没有回复,那么无法确定服务器是否成功接收到.
可假设几种不同的原因:
(1) 由于网络问题,服务器就是没有收到请求.
(2)服务器虽然成功收到请求,也处理了,但是回复客户端时网络出现问题;
(3)服务器虽然成功收到请求,也处理了,但是回复客户端时服务器出现问题;


四次挥手
一般情况下通信双方中任意一方主动发起关闭请求, 普遍来说由客户端来主动发起关闭.

(1)首先客户端发出断开连接的请求,携带FIN终止序列编号与seq=x+2,以及ACK=y+1确认序列编号,进入到终止等待1状态FIN_WAIT_1;
(2)服务器收到消息后,可能服务端还有一些后序的操作,此时发出ACK=x+3的确认序列编号,先确认收到消息了;进入 关闭等待状态CLOSE_WAIT;
(3)客户端收到回复到,进入终止等待2状态FIN_WAIT_2;
(4)服务端此时可以向客户端发出数据,进行自己的操作, 结束后,可以向 客户端发出关闭终止请求;包含终止序列编号FIN以及seq=y+1;自己进入最终确认状态LAST_ACK.
(5)客户端收到请求后,给与回复,包含确认序列编号ACK=y+2,自己进入超时等待状态TIME_WAIT.


当然也有特殊的案例,通信双方同时发出关闭请求;双方都处于终止等待1FIN_WAIT_1状态,此时收到对方的ACK,双方又进入到CLOSING关闭中状态, 之后一起到达超时等待状态TIME_WAIT,经过一段时间后进入到关闭状态.


为什么客户端在最后一次确认之后,要进入超时等待状态TIME_WAIT,而不是直接close关闭呢?

  • 当客户端与服务端都进入到CLOSE状态,可能还有某些数据包在网络上走动,
  • 注意:一个连接是由4元组唯一标识[客户端IP, 客户端Port,服务端IP,服务端Port], 这个连接关闭之后再重开,这就应该是一个新连接,可是4元组无法区分新连接和旧连接,
  • 这样导致:之前走动的数据包就可能跑到这个新的连接上;

所以在TCP的四次握手时,客户端最后一次发完确认消息后就会进入到TIME_WAIT状态,避免旧的数据包跑到新连接上面.
任何一个Ip的数据包在网络上存活的时间为 MSL(Maximum Segment LifeTime) 默认为120S.;也就是说如果超出了这个时间,中间的路由节点就会把这个数据丢弃.
TIME_WAIT状态会持续2倍的MSL 时间,足够防止其他数据包串到通信双方的连接处.


为什么设定为2倍的时间
由于网络2将军问题,第四次发送的数据包,服务器不确定是否可以收到,那么如果服务器没有收到,就需要向客户端重新发送第三次数据包,然后客户端收到之后就明白服务器没收到第四次的数据包,最终客户端就会重新发出第四个的数据包.

分析之后,那么 客户端发送第四次数据包和服务器重新发送第三次数据包时,两次的最长时间为2MSL,所以设定为2倍的MSL等待时间.


客户端有TIME_WAIT状态,为何服务器不设定呢?

一方面考虑到服务端的利用问题,服务端本来收到最后一次挥手确认后就关闭了,要是还等2MSL时间,可能会让服务器耗费时间在这里.
方面二: 每个连接都是一个4元组,同时关联客户端与服务端. 当客户端处于TIME_WAIT状态之后,这个连接就需要2倍的MSL时间后才可以重新启用.


如何防止大量的连接处于TIME_WAIT超时等待状态
如果频繁地创建出连接,就可能导致大量连接处于超时等待状态, 消耗过多的连接资源;
(1)避免服务器主动关闭连接, 那么服务端就不会处于超时等待状态;
(2)在客户端进行连接使用时,可以复用连接,不要频繁创建关闭,消耗资源.


3.TCP的粘包与分包 , 数据分段


Socket编程:
粘包案例:

  • 客户端write写操作两次, 产生2个数据包;假设 "abc" , "def"
  • 服务端read读一次,可能读到"abcdef" 或许是"abcd",后面的"ef"在下次被读取到.

分包案例:

  • 客户端write写操作1次,产生1个数据包,假设为"abcdef"
  • 服务端read读操作2次, 读到2个数据包, 即"ab" , “cdef”.

由于TCP是一个面向流的协议,并不管理应用层的数据包之间的分界.

  • 可能发送一次, N次接收才能完成;
  • 可能发送N次,一次就给接收完毕;

如何解决粘包/分包 , 具体还是需要逻辑业务完成;
方式(1)可以在每个数据包前,加一个 长度为4字节的字段.
案例:

  • 发送方:数据包1,2,3 .大小不固定,变长. 每次发送数据包时,在头部先加长度为4字节的字段.
  • 接收方: 每次接受数据时,先固定读4个字节,解析后得到数据包1的长度,然后再读取,当读取的数据达到这个长度时,就说明数据包1已经接收完成. 重复后面的操作…

方式(2):在每个数据包的前后部分,加一个固定长度的特殊标记. 在接收时根据前后的标志确定当前的数据包是否读取完成; 但是如果两个数据包以及特殊标记一样了,就无法区分了.


数据分段问题MSS

在理想情况下,数据经过一次写操作即可进入TCP,封装IP,然后传到以太网.

但如果要发送的业务数据,超出以太网报文最大值MTU[Maximum Transmission Unit], 通常为1500字节.

比如数据传到TCP时,TCP头占用20字节,在包装到IP层时,IP头又占用20字节,层层叠加,最后到以太网时就可能超出最大报文值.

  • 那么就得在IP层对数据进行分包: 在IP层中,若数据包大小已经超出了MTU,那么就需要做IP分片,将一个数据包分为多个数据片.
  • 怎么避免大量的IP分片产生呢? 在TCP进行连接时,通信双方就需要协商MSS值[TCP最大报文段值].
  • 或者直接计算MSS = MTU - tcp头部20字节 - IP头部20字节 = 1460字节.

需要注意的一点是,即使预先协商了可行的MSS[TCP最大报文段值],也可能会出现IP数据分片;
由于这个IP层可通信不同结构的局域网,有可能某个局域网的MTU小于1500呢


网络协议tcp三次握手,四次挥手

【网络协议】TCP三次握手,四次挥手1:三次握手可以先看看tcp的协议的图序列号seq:占4个字节,用来标记数据段的顺序,TCP把连接中发送的所有数据字节都编上一个序号,第一个字节的编号由本地随机产生;给字节编上序号后... 查看详情

tcp三次握手和四次挥手

...是客户端突然出现故障了怎么办?背景描述通过上一篇中网络模型中的IP层的介绍,我们知道网络层,可以实现两个主机之间的通信。但是这并不具体,因为,真正进行通信的实体是在主机中的进程,是一个主机中的一个进程 查看详情

tcp三次握手四次挥手

...,中文可以译为“报文最大生存时间”,他是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。因为tcp报文(segment)是ip数据报(datagram)的数据部分,具体称谓请参见《数据在网络各层中的称呼》一文TIME_WAIT根... 查看详情

计算机网络概述传输层三次握手和四次挥手

 三次握手TCP协议中,主动发起请求的一端称为『客户端』,被动连接的一端称为『服务端』。不管是客户端还是服务端,TCP连接建立完后都能发送和接收数据。起初,服务器和客户端都为CLOSED状态。在通信开始前,双方都得... 查看详情

tcp中三次握手与四次挥手(代码片段)

...次挥手”,本以为这就是TCP,但其实TCP远不止这些。面对网络中纷繁复杂的情况,作为承诺传输可靠的TCP协议,需要解决很多问题。例如:怎么保证数据是可靠的?---连接确认,关闭确认,收到数据确认,各种确认因为网络或其... 查看详情

计算机网络——tcp三次握手和四次挥手详解(代码片段)

文章目录1、三次握手1.1connect()、listen()和accept()三者之间的关系1.1三次握手的过程1.2三次握手的状态转换和安全问题1.3三次握手的问题汇总2、四次挥手2.1四次挥手的过程1.2四次挥手的问题汇总3.1TCP编程中三次握手和四次挥手的全... 查看详情

tcp三次握手四次挥手

...务器端和客户端之间需要进行三次交互:OSI参考模型中的网络层,在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。(TCP在运输层,IP在网络层)第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器... 查看详情

网络通信——tcp“三次握手““四次挥手“详解

TCP三次握手和四次挥手是面试题的热门考点,它们分别对应TCP的连接和释放过程前言TCP三次握手和四次挥手是面试题的热门考点,它们分别对应TCP的连接和释放过程1.TCP通信包含那几步?TCP通信过程包括三个步骤:建立TCP连接通... 查看详情

tcp三次握手,四次挥手(代码片段)

...放连接时,等待2MSL的意义?答:1.保证ack传过去。2.消除网络中所有其他的包。问:为什么需要四次挥手才能断开连接?答:全双工,FIN,ACK问:出现大量的CLOSE_WAIT的原因?答:服务器忙于读写。附大佬总结的:https://github.com/wang... 查看详情

计算机网络--tcp三次握手和四次挥手

TCP(传输控制协议)  TCP(TransmissionControlProtocol传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。通过三次握手建立连接,通讯完成时要拆除连接,由于TCP是面向连接的所以只能用于端到端的通讯。... 查看详情

java网络原理之连接管理:tcp三次握手和tcp四次挥手

问题:TCP为什么是三次握手?而不是两次或者四次?TCP作为种可靠传输控制协议,其核心思想:既要保证数据可靠传输,又要提高传输的效率,而用三次恰恰可以满足以上两方面的需求!TCP可靠传输的精髓:TCP连接的发送方A,由操作系... 查看详情

tcp协议tcp的三次握手和四次挥手

文章目录前言TCP连接的三个阶段TCP数据报介绍TCP三次握手(Three-wayHandshake)三次握手的过程握手过程说明为什么需要三次?两次握手会发生什么问题?数据传输TCP四次挥手四次挥手的过程挥手过程说明握手需要三次,为... 查看详情

tcp协议tcp的三次握手和四次挥手

文章目录前言TCP连接的三个阶段TCP数据报介绍TCP三次握手(Three-wayHandshake)三次握手的过程握手过程说明为什么需要三次?两次握手会发生什么问题?数据传输TCP四次挥手四次挥手的过程挥手过程说明握手需要三次,为... 查看详情

tcp协议三次握手/四次挥手

TCP是传输控制协议,需要建立链接,通过三次握手和四次挥手保证数据传输的可靠性三次握手过程三次握手的目的在于,确认双方的通信能力是否正常第一次握手,客户端发送连接请求的报文给服务端第二次握手,服务端接收请求后回... 查看详情

tcp三次握手和四次挥手

...下四个层次:  1.链路层,也称作数据链路层或者网络接口层,通常包括操作系统中的设备驱动程序和计算机中对应的网络接口卡。它们一起处理与电缆(或其他任何传输媒介)的物理接口细节。2.网络层,也称作互联网... 查看详情

图解tcp的三次握手和四次挥手

文章目录TCP的三次握手与四次挥手三次握手四次挥手其中细节三次握手为什么要有最后一次ACK?四次挥手为什么需要四次挥手?TCP的三次握手与四次挥手三次握手三次握手过程(1)客户端发送一个SYN0给服务器ÿ... 查看详情

图解tcp的三次握手和四次挥手

文章目录TCP的三次握手与四次挥手三次握手四次挥手其中细节三次握手为什么要有最后一次ACK?四次挥手为什么需要四次挥手?TCP的三次握手与四次挥手三次握手三次握手过程(1)客户端发送一个SYN0给服务器ÿ... 查看详情

tcp/ip协议三次握手和四次挥手大白话解说

...四次挥手却忘了,这是大学习里学过的,奋而翻阅书籍和网络对之前所学的做一个温顾,算是夯实自我吧。TCP(TransmissionControlProtocol)网络传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议,数据传输前建... 查看详情