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三次挥手的原因&TCP延迟确认机制

在学习wireshark抓包的时候,一般都从最简单的三次握手和四次挥断看起,因为这两步对于每一个完整健康的TCP交互流来说都是必不可少的,通过抓包我们可以更清楚的了解其工作机制。

一、四次挥手和“三次挥手”

1、第一种情况
在这里插入图片描述
从抓包来看是很正常的三次握手和四次挥断

1.服务端FIN :Seq = a , Ack = b #我想断开连接
2.客户端ACK:Seq = b, Ack = a+1 #收到,断开吧
3.客户端FIN :Seq = b, Ack = a+1 #我也想断开连接
4.服务端ACK:Seq = a+1, Ack = b+1 #收到,断开吧

2、第二种情况
在这里插入图片描述
分别是:

1.客户端FIN :Seq = a , Ack = b #我想断开连接
2.服务端FIN :Seq = b, Ack = a+1 #收到,断开吧。我也想断开连接
3.客户端ACK:Seq = a+1, Ack = b+1 #收到,断开吧

  • 这么看来是第二步和第三步合并了,那为什么会合并呢?

在林沛满老师的《Wireshark网络分析就这么简单》一书中的第123页图11有出现过这种情况,其原因也在早年的一篇博客文章中也有提到,即 TCP的延迟确认 机制导致。

二、什么是TCP的延迟确认?

RFC 1122文档中的 4.2.3.2 When to Send an ACK Segment 小节有过对延迟确认机制下何时发送ACK的描述:

4.2.3.2 When to Send an ACK Segment
————
A host that is receiving a stream of TCP data segments can increase
efficiency in both the Internet and the hosts by sending fewer than
one ACK (acknowledgment) segment per data segment received; this is
known as a “delayed ACK” [TCP:5].
————
A TCP SHOULD implement a delayed ACK, but an ACK should not be
excessively delayed; in particular, the delay MUST be less than 0.5
seconds, and in a stream of full-sized segments there SHOULD be an ACK
for at least every second segment.
————
DISCUSSION:

A delayed ACK gives the application an opportunity to update the
window and perhaps to send an immediate response. In particular, in
the case of character-mode remote login, a delayed ACK can reduce the
number of segments sent by the server by a factor of 3 (ACK, window
update, and echo character all combined in one segment).
————
In addition, on some large multi-user hosts, a delayed ACK can
substantially reduce protocol processing overhead by reducing the
total number of packets to be processed [TCP:5]. However, excessive
delays on ACK’s can disturb the round-trip timing and packet
“clocking” algorithms [TCP:7].

简单的概括:TCP延迟确认机制,允许接受方在接收到数据帧时不马上回复ACK,而是可以等待一段时间再回复ACK,但这个时间不得大于0.5s(该时间可修改,Windows默认200ms,也可通过参数关闭机制)。

RFC 1122规定,Delayed ACK对单个的小报文可以延长确认的时间,但不允许有两个连续的小报文不被确认。所以,当发送端连续发送两个报文后,接收端必须给予确认。(这点待讨论,很多抓包情况下确实有>2个包才发ACK的情况,这篇文章从代码上也对这个问题进行了讨论分析TCP delay ack机制和实现

这个延时时间需要注意,它不是在接收到数据的时候开始计时,而是内核会启动一个200ms的定时器,每隔200ms就会检查一次是否有ACK发送,比如定时器在0ms启动,200ms到期,100ms的时候接收到数据,那么200ms的时候没有响应数据,ACK会被发送,这个情况下只延迟了100ms.

  • 那这个作用是什么呢?
    一般来说TCP数据交互过程中,接收方A每收到发送方B发出的一个报文,接收方A需要回复发送方B一个ACK报文,告知我已收到这个包,可以发送下一个。但是在延时大或者拥塞的网络环境上,这种一来一回的交互缺点明显,ACK单独成包代价高,而在TCP延迟确认机制下有如下表现:
    在这里插入图片描述
    即当客户端收到服务器发来的数据后,如果没有数据要发送给对端,则等待一段时间,如果这段时间内有数据要发给服务器的话,会与ACK合并发送(确认这段时间所收到的数据),延迟确认没有直接提高性能,只是减少了部分确认包,减轻网络负担,当然这是一把双刃剑,某些情况下需要关闭。

回到正题,TCP延迟确认机制 对四次挥断也同样生效,第二步的服务端延迟到了和第三步一并发送,服务器收到了客户端的FIN,等待一段时间看自己有没有数据要发给客户端,然后自己也想断开连接,FIN就和ACK一起发送:

1.客户端FIN :Seq = a , Ack = b #我想断开连接
2.服务端FIN :Seq = b, Ack = a+1 #收到,断开吧。我也想断开连接
3.客户端ACK:Seq = a+1, Ack = b+1 #收到,断开吧

  • 那既然要结束会话了,为什么服务端还要等待发送数据呢?

    TCP链接是一个全双工的通道,客户端发送了FIN,只表明客户端要结束会话,即自己不再发送数据,但是还可以继续接收数据,因为服务器没有发FIN,服务器也可以继续发送数据。

  • 那什么时候会四次挥断什么时候“三次挥断”呢?

    看被动断开TCP链接的系统是否开启了延迟确认(delay ack),如果没有开启,正常情况下是不会等待FIN,需要立刻回复ACK的,即四次挥断。

  • 另提一下:
    其实TCP不是通信的全部,TCP服务于application,即应用。 假设客户端A发起断开与服务端B的连接:
    1.用户在客户端操作触发断链,此时A的application接受用户的断开请求,信号到达A的TCP层;
    2.于是A的TCP层发送FIN包?B的TCP层;
    3.B接收到A的FIN,需要告知B的application:“A要断开TCP链接,你还有数据要给A的吗?” 然后等待application的回复,在收到FIN的同时立刻回复ACK给A,A?B方向断开;
    4.如果有数据需要传输则继续发送,传完后application发送close给B的TCP层,告知可关闭链接;
    5.于是B的TCP层发送FIN?A的TCP层,A回复ACK后,B?A方向也断开,结束。

参考知乎车小胖老师的回答:https://www.zhihu.com/question/50646354

三、Nagle算法

有这么一种情况,我在国外买了一台服务器搭VPN,从国内连过去后敲一串字符:fdfhaudifhidbfidvfaiudh,每个字符并不大,但是却需要封装成小包逐个发送出去,那是否有机制允许这些小包合并成一个打包一起发送出去呢?有,Nagle算法。
在这里插入图片描述

百度百科中对其做了详细的解释:Nagle算法

  • 为了尽可能的利用网络带宽,TCP总是希望尽可能的发送足够大的数据。(一个连接会设置 MSS(单个报文的最大报文段长度) 参数,因此,TCP/IP希望每次都能够以MSS尺寸的数据块来发送数据)。Nagle算法就是为了尽可能发送大块数据,避免网络中充斥着许多小数据块。

  • Nagle算法的基本定义是任意时刻,最多只能有一个未被确认的小段
    所谓“小段”,指的是小于MSS尺寸的数据块,所谓“未被确认”,是指一个数据块发送出去后,没有收到对方发送的ACK确认该数据已收到。

  • Nagle算法的规则(可参考tcp_output.c文件里tcp_nagle_check函数注释):

(1)如果包长度达到MSS ,则允许发送; #即达到单个包最大值,此刻发出数据包
(2)如果该包含有FIN,则允许发送;
(3)设置了TCP_NODELAY选项,则允许发送;#打开TCP_NODELAY选项,则意味着无论数据包是多么的小,都立即发送(不考虑拥塞窗口)
(4)未设置TCP_CORK选项时,若所有发出去的小数据包(包长度小于MSS)均被确认,则允许发送;#当TCP_CORK选项被设置时,TCP链接不会发送任何的小包,即只有当数据量达到MSS时,才会被发送
(5)上述条件都未满足,但发生了超时(一般为200ms),则立即发送。

Nagle算法对传输的优化:
在这里插入图片描述
同样Nagle算法也有其弊端,即不适用于所有场景,像上面这个例子,远程终端无法实时显示输入的字符,也无法通过TAB键来实时补全指令,因为它要收集齐一个MSS或者等超时后才发送给服务器。另在一些敏感业务和对实时数据要求高的场景,比如CSGO下,你看到敌人要偷你的队友,恰好你黄雀在后,想来个headshot,结果点了鼠标没反应,没到一个MSS,点击鼠标的指令没有发送给服务器,那你就等着被队友抽

四、当Nagle算法遇到Delayed ACK

建议参考本文,有很详细的解释:https://my.oschina.net/xinxingegeya/blog/485643

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-08-24 15:54:17  更:2021-08-24 15:56:02 
 
开发: 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 21:15:14-

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