tcp shutdown, fin_wait1, fin_wait2, close_wait, last_ack, 谢特!

TCP 作为双向传输协议,如果你想只收不发,可以单向关掉发,shutdown(socket.SHUT_WR),但不建议这么做。

看以下代码:

#!/Users/zhaoya/myenv/bin/python3
# client
import socket

client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('127.0.0.1', 12345)
client_socket.connect(server_address)
client_socket.shutdown(socket.SHUT_WR) # 单向关闭发

while True:
    try:
        data = client_socket.recv(1024)
        if not data:
            break
        print(f"recv: {data.decode()}")
    except:
        break

client_socket.close()
#!/Users/zhaoya/myenv/bin/python3
# server
import socket

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('127.0.0.1', 12345)
server_socket.bind(server_address)
server_socket.listen(1)

client_socket, client_address = server_socket.accept()

while True:
    try:
        data = "xxxxx"
        client_socket.send(data.encode())
        print(f"send: {data}")
    except:
        break

client_socket.close()
server_socket.close()

运行后:
在这里插入图片描述

状态很奇怪,人们很难接受一个连接在非 ESTABLISHED 状态下正常传输数据,这会引来一堆咨询,但根据 TCP 状态机,这又是合理的,client 单向关闭了发送,FIN 就过去了,server 回复了 FIN,进入 CLOSE_WAIT,client 收到回复进入 FIN_WAIT_2,而 server 在 CLOSE_WAIT 下发数据,client 在 FIN_WAIT_2 下是完全合理的。

为了少惹是生非,换一个方向,在 server 侧关闭掉收,client_socket.shutdown(socket.SHUT_RD),就香了:

client_socket, client_address = server_socket.accept()
client_socket.shutdown(socket.SHUT_RD) # 单向关闭收

此时状态很正常:
在这里插入图片描述

故,shutdown 的 SHUT_RD 仅影响 socket 接口(仅仅在读的时候报错,让你读不出去),不影响 TCP 状态。

再看纷扰的 FIN_WAIT_1/2。

TCP 的 RFC793 并未规定状态超时时间,为完整闭环这是合理的。但至少 Linux kernel 的 TCP 实现用不同的机制指定了 FIN_WAIT_1/2 的超时时间:

  • FIN_WAIT_1 超时时间由 net.ipv4.tcp_orphan_retries 控制:如果一直收不到针对 FIN 的 ACK,在彻底销毁这个 FIN_WAIT_1 连接前,等待的 RTO 退避次数;
  • FIN_WAIT_2 超时时间由 net.ipv4.tcp_fin_timeout 控制:默认值通常 60 秒。

这就带来了问题,如果按照上述第一种在 client 关闭发送方向的做法,连接进入 FIN_WAIT_2 状态,在 tcp_fin_timeout 之后连接将不可用(进入 TIME_WAIT),这可能并不符合 shutdown(WR) 调用者的意图。

换句话说 CLOSE_WAIT 明确在说 “我已经收到了对端的 FIN,正等着应用程序调用 shutdown + close 结束连接”,这意思是,只要一端发送了 FIN,另一端应用程序在一个预期的不太久的时间内关闭连接是意料之中的,也就是不建议连接在 CLOSE_WAIT + FIN_WAIT_2 的状态继续传输数据。但如果应用程序希望如此呢?只能在对端 shutdown(RD) 了。

TCP 挥手断连期间的其它超时时间相对还好理解,比如 LAST_ACK 状态的超时时间和 FIN_WAIT_1 一致,由 net.ipv4.tcp_orphan_retries 控制。

So?TCP 的挥手状态太复杂且歧义了,一般的咨询类问题也都围绕着这些状态,加上 “应用程序忘了 close”,“没有 shutdown 优雅关闭”,“多线程 socket 描述继承 + 优雅关闭” 等等问题更让人抓狂。

更合理的做法应将协议实现部分单独抽出一个控制面,用 keepalive 来 probe 连接,而不是靠内置状态的超时机制。TCP 标准规定某些状态可能就是无限等待,实现就不能自行安排超时。然而由于 TCP 一开始即带内控制,keepalive 可能是另一个问题(采用 out of window 序列号)而不是方案,参见 对 oow 的建议,一直在见缝捡漏。

浙江温州皮鞋湿,下雨进水不会胖。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/905076.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

怎么知道社媒上用户在讨论品牌什么?评价如何?

现在社交媒体不再仅是人们闲聊和分享生活片段的地方,更是品牌了解市场趋势和消费者需求的重要渠道。所以做号社媒上用户声音的聆听,企业更能抓住客户需求、抢占潜力市场,进一步占据更多市场份额,获得精准客户。 做好用户声音聆听…

【QT】Qt窗口(上)

个人主页~ Qt窗口 一、菜单栏二、工具栏三、状态栏四、浮动窗口五、对话框1、简介(1)模态对话框(2)非模态对话框(3)混合属性对话框 Qt窗口是通过QMainWindow类来实现的,我们之前的学习是通过QWi…

第二十章 Vue组件通信之父子通信

目录 一、引言 二、组件关系分类 三、组件通信的解决方案 3.1. 父子通信流程图 3.2. 父组件通过 props 将数据传递给子组件 3.2.1. 代码App.vue 3.2.2. 代码MySon.vue 3.3. 子组件利用 $emit 通知父组件修改更新 ​编辑3.3.1. 代码App.vue 3.3.2. 代码MySon.vue 3…

用ChatGPT提升工作效率:从理论到实际应用

伴人工智能技术的迅速演进,像ChatGPT这类语言模型已成为提升工作效率的关键工具。这类模型不仅具备处理海量数据的能力,还能自动化许多日常任务,从而提高决策的准确性。本文将深入探讨如何在工作中利用ChatGPT等AI工具提升效率,涵…

golang 服务注册与服务发现框架 入门与实践

Go语言中服务注册与发现的应用 在Go微服务架构中,服务注册与服务发现是实现服务间通信和解耦的关键。随着服务数量的增长,手动管理服务之间的依赖关系变得异常复杂且容易出错。因此,自动化服务注册与发现机制变得尤为重要。当一个Go微服务启…

1.STM32之定时器TIM---第一部分(基本定时器)(功能最强大结构最复杂的一个外设)(实验基本定时功能)-----定时器定时中断(利用内部时钟72M)

定时器TIM是STM32外设中功能最强大结构最复杂的一个外设!Whappy STM32F103C8T6总共由一个高级定时器3个通用定时器 #include "stm32f10x.h" // Device header #include "Delay.h" #include "OLED.h" #include &quo…

无人机救援系统基本组成

无人机救援系统基本组成 1. 源由2. 组成2.1 无人机载具2.1.1 多旋翼2.1.2 垂起固定翼2.1.3 智能避障2.1.4 物资投递 2.2 智能吊舱2.2.1 云台2.2.2 高清摄像2.2.3 红外热成像2.2.4 激光测距2.2.5 目标跟踪 2.3 通讯链路2.3.1 超长距离通信2.3.2 长距离通信2.3.3 中等距离通信 2.…

CSS 复习

复杂选择器可以通过(id的个数,class的个数,标签的个数)的形式,计算权重。 如果我们需要将某个选择器的某条属性提升权重,可以在属性后面写!important;注意!importent要写在;前面 很多公司不允许…

uniapp一键打包

1.先安装python环境, 2.复制这几个文件到uniapp项目里面 3.修改自己证书路径,配置文件路径什么的 4.在文件夹页面双击buildController.py或者cmd直接输入buildController.py 5.python报错,哪个依赖缺少安装哪个依赖 6.执行不动的话&…

SINAMICS V90 在汽车行业中的应用-天拓四方

随着生活水平的提高,平均每家每户都配有一辆代步用的小汽车,汽车行业也正处于蓬勃的发展中,尤其是新能源汽车,带来了新一轮的汽车生产热潮。生产一辆汽车,从零配件的加工,到整车的组装,基本已经…

C++算法第五天

本篇文章继续和大家一起刷算法题 第一题 题目链接 . - 力扣(LeetCode) 题目解析 题目要求: 这是一个连续的子数组 计算子数组内元素的和,若数组内元素的和符合 > target的值并且该子数组的长度是最短的,则返回…

【电机控制器】以STC8H1K系列举例——持续更新

【电机控制器】以STC8H1K08 举例——持续更新 文章目录 [TOC](文章目录) 前言一、代填二、参考资料总结 前言 使用工具: 提示:以下是本篇文章正文内容,下面案例可供参考 一、代填 二、参考资料 STC8H1K系列数据手册 梁工——BLDC, 三相无…

如何快速给word文件里的文字加拼音?请看详细步骤

怎么快速给word文件里的文字加拼音?在日常的文字处理工作中,很多人可能会遇到一个问题:如何在Word文档中为文字添加注音。尤其是对于一些需要帮助读音的文本,比如中文学习材料、教材或儿童读物,注音可以帮助读者更好地…

AI跟踪报道第62期-本周AI新闻: 微软推出Copilot的AI Agent和Computer Control

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

C++学习:类和对象(一)

一、面向过程与面向对象编程 1. 什么是面向过程编程? 面向过程编程(Procedural Programming)是一种以过程(或函数)为中心的编程范式。程序被视为一系列按顺序执行的步骤,主要通过函数对数据进行操作 特点…

mac|maven项目在idea中连接redis

安装maven brew install maven idea-setting导入redis插件 idea新建maven项目 构建系统选择maven 项目右侧数据库图标导入redis 新建一个数据库&#xff0c;名称必须为数字&#xff0c;测试一下是否可以连接&#xff0c;连接成功后选择确定 pom.xml导入redis <depende…

开发了一个成人学位英语助考微信小程序

微信小程序名称&#xff1a;石榴英语 全称&#xff1a;石榴英语真题助手 功能定位 北京成人学士学位英语辅助学习工具&#xff0c;包含记高频单词&#xff0c;高频词组&#xff0c;专项练习&#xff0c;模拟考试等功能。 开发背景 个人工作需要提高学习英文水平&#xff…

GitLab代码仓管理安装配置使用

Gitlab介绍 GitLab是一个基于Git的开源项目管理工具&#xff0c;它集成了版本控制、代码审查、持续集成&#xff08;CI&#xff09;/持续部署&#xff08;CD&#xff09;、自动化测试等多种功能&#xff0c;是一个完整的DevOps平台。以下是对GitLab的详细介绍&#xff1a; 一…

C# Retry库

比如网络访问或硬件参数设置需要重试&#xff0c;可引用gunet上的Polly库。 同步方式&#xff08;每次重试有不同的时间间隔&#xff09; var polly Policy.Handle<Exception>().WaitAndRetry(new[] { new TimeSpan(0, 0, 1), new TimeSpan(0, 0, 2), new TimeSpan(0, …

[论文阅读] Improved Baselines with Visual Instruction Tuning

启发&#xff1a; 1、LLaVA-1.5和LLaVA以及其他大模型相比&#xff0c;做出了哪些改进&#xff1f; &#xff08;1&#xff09;使用CLIP-ViT-L-336px作为视觉编码器&#xff0c;使模型能处理336px的高分辨率图像&#xff0c;这使得模型能从图像中提取出更多细节信息。此外&am…