IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> TCP通信过程理解 -> 正文阅读

[网络协议]TCP通信过程理解

最近在测试TCP通信的时候偶然发现挥手关闭连接的时候只进行了3次挥手,所以有必要详细了解下TCP通信的过程。

相关概念

? ? 序列号Seq:占4个字节,用来标记数据段的顺序,TCP把连接中发送的所有数据字节都编上一个序号,第一个字节的编号由本地随机产生;给字节编上序号后,就给每一个报文段指派一个序号;序列号seq就是这个报文段中的第一个字节的数据编号。

? ? 确认号Ack:占4个字节,期待收到对方下一个报文段的第一个数据字节的序号;序列号表示报文段携带数据的第一个字节的编号;而确认号指的是期望接收到下一个字节的编号;因此当前报文段最后一个字节的编号+1即为确认号。

? ? 确认标识ACK:占1位,仅当ACK=1时,确认号才有效;ACK=0时,确认号无效。

? ? 同步标识SYN:连接建立时用于同步序号。当SYN=1,ACK=0时表示的是一个连接请求报文段。若同意连接,则在响应报文段中使得SYN=1,ACK=1。因此,SYN=1表示这是一个连接请求报文,或连接接受报文。SYN这个标志位只有在TCP建立连接时才被置为1,握手完成后SYN标志位被置为0。

? ? 终止标识FIN:用来释放一个连接。FIN=1表示:此报文段发送方的数据已经发送完毕,并要求释放运输连接

? ? 注意:ACK、SYN和FIN等大写的单词表示标志位,其值要么是1,要么是0;ack、seq小写的单词表示序号。以下是常用的标识符:

常用标识含义
URG紧急指针是否有效。为1时该段会被优先处理
ACK确认数据包成功接收,一般置为1。
PSH提示接收端应用程序立即从TCP缓冲区把数据读走。
RST重置连接,复位。
SYN请求建立连接,并在其序列号的字段进行初始值设定。建立连接,设置为1
FIN希望断开连接,这个过程中可能还会继续接收数据。

TCP的三次握手过程理解

第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入SYN_SENT状态,等待服务器确认;

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

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
以下是抓包工具显示的3次握手的细节:

TCP数据传输过程理解


? ? ? ? TCP连接是双工的,连接的双方都可以主动发起数据传输,不过无论是那方发起TCP数据传输,都需要收到对方的确认才能认为对方收到了数据。发送方收到了ACK,表明接收方已经接收到数据,保证了数据的可靠达到。如果一定时间内未收到对方的ACK确认,就会重新发送TCP数据包。
? ? ? ? 接收方在收到数据后,并不会立即回复ACK,多个数据包可能只会收到一个ACK确认,这是由于ACK延迟确认机制引起的。一般ACK延迟发送的时间为200ms,但这个200ms并非收到数据后需要延迟的时间。系统有一个固定的定时器每隔200ms会来检查是否需要发送ACK包。这样做有两个目的:
1、ACK是可以合并的,也就是说如果连续收到两个TCP包,并不一定需要ACK两次,只要回复最终的ACK就可以了,降低了网络流量。
2、如果接收方有数据要发送,那么就会在发送数据的TCP数据包里,带上ACK信息。这样做,可以避免大量的ACK都以单独的TCP包发送,减少了网络流量

TCP的四次挥手过程理解?

1)客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
2)服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT状态。TCP服务器通知上层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经不能发送数据了,但服务器依然可以向客户端发送数据。这个状态会持续一段时间(CLOSE-WAIT状态持续的时间)。客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
3)服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于是半关闭状态,服务器可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
4)客户端收到服务器的连接释放报文后,发出确认报文,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT状态。注意此时TCP连接还没有释放,必须经过2?MSL(2倍最长报文段寿命)的时间(默认4分钟)后,才进入CLOSED状态,释放套接字资源。服务器收到客户端发出的确认后,立即进入CLOSED状态,结束这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早。

常见问题总结


1.为什么连接时是3次握手,关闭时却是4次挥手?是否总是4次挥手?

? ? ? ? 因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到Server端所有的报文都发送完,才能发送FIN报文,因此需要四步挥手。当然也并不总是四次挥手,当Server端收到FIN报文后如果没有需要发送的数据报文,中间的FIN和ACK可以合并一起进行发送,此时就是3次挥手。
以下抓包截图就只有3次挥手:

2.为什么不能用两次握手进行连接?

? ? ? ? 3次握手需要完成两个重要的功能,既要双方作好发送数据的准备工作(双方都知道彼此已准备好),也需要双方就初始序列号进行协商一致,这个序列号在握手的过程中被发送和确认。

? ? 如果只进行两次握手,可能会造成死锁。考虑计算机S和C之间的通信,假定客户端C给服务器端S发送一个连接请求SYN,S收到了这个SYN,并发送了确认应答ACK。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据了。此时S对C的连接确认应答ACK如果在传输中丢失,C将不知道S是否已准备好,也不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分组,只等待连接确认应答分组。而S在发出的数据分组超时后,重复发送同样的分组。这样就形成了死锁。

3.为什么TIME_WAIT状态需要经过2MSL才能返回到CLOSED状态??

? ? ? ? 虽然按道理讲,四个报文都发送完毕,可以直接进入CLOSED状态,但是网络是不可靠的,有可能最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复时,该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接

4.如果已经建立了连接,但是客户端突然出现故障了怎么办?

? ? ? ? TCP有一个保活计时器,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没回应,服务器就认为客户端出了故障,接着就关闭连接。

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-08-31 15:49:47  更:2021-08-31 15:50:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 22:59:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码