当前位置: 首页 > news >正文

TCP协议的RST标志

下文中的内容多数来自【参考】中的文章,这边进行一个整理和总结,后续会慢慢增加出现各个 RST 包的测试代码,便于理解。

TCP的 “断开连接” 标志

  1. RST 标志

    Reset,复位标志,用于非正常地关闭连接。它是 TCP 协议首部里的一个标志位。发送 RST 包关闭连接时,直接丢弃缓冲区的包并发送 RST 包,而接收端收到 RST 包后,也不必发送 ACK 包来确认。

    TCP 套接字在任何状态下,只要收到 RST 包,即可进入 CLOSED 初始状态,不会有任何回应。至于是否通知上层应用,要根据应用程序是阻塞模式还是非阻塞模式:

    • 阻塞模型下,内核无法主动通知应用层出错,只有应用层主动调用 read() 或者 write() 这样的 IO 系统调用时,内核才会利用出错来通知应用层对端 RST。
    • 非阻塞模型下,select 或者 epoll 会返回 sockfd 可读,应用层对其进行读取时,read() 会报错 RST。
  2. FIN 标志

    发端完成发送任务标识。用来释放一个连接。FIN=1 表明此报文段的发送端的数据已经发送完毕,并要求释放连接。

  3. RST 和 FIN 的区别

    • 正常地关闭连接用 FIN 标志位,但 FIN 标志位不能用来处理异常情况;
    • RST 会导致连接立即终止,而在 FIN 中会得到确认。

TCP 出现 RST 包的情况

  1. 连接未监听的端口

    连接一个未监听的端口,则被连接方会发送一个 RST。也就是说主机传输层 TCP 程序接收到一个 SYN 包,而这个 SYN 包目的端口并没有 socket 监听,那么主机的协议栈会直接回复一个 RST。

  2. 向已关闭的连接发送数据

    顾名思义,主机传输层 TCP 协议程序接收到一条 TCP 数据段,而目的端口并没有 socket 监听,那么主机的协议栈会直接回复一个 RST。

  3. 向已关闭的连接发送 FIN

    主机传输层 TCP 协议程序接收到一条 FIN,而目的端口并没有 socket 监听,那么主机的协议栈会直接回复一个 RST。

  4. 向已经消逝的连接中发送数据

    和上面的举例相同。

  5. 处理半打开连接

    一方关闭了连接,另一方却没有收到结束报文(如网络故障),此时另一方还维持着原来的连接。而一方即使重启,也没有该连接的任何信息。这种状态就叫做半打开连接。而此时另一方往处于半打开状态的连接写数据,则对方回应 RST 复位报文。此时会出现 connect reset by peer 错误。详见下文测试代码。

  6. 目的主机或网络路径中的防火墙拦截

    如果目的主机或者网络路径中显式的设置了对数据包的拦截,如使用 iptables 对主机的防火墙添加了一条规则,对于目的端口是 6000 的 TCP 报文,丢弃并回复 RST。

  7. TCP 接收缓冲区 Recv-Q 中的数据未完全被应用程序读取时关闭该 socket

    接收到的数据缓存在缓冲区 Recv-Q,它们等待被上层应用取走,如果缓冲区 Recv-Q 有数据未被应用取走,而此时调用 close 函数关闭 TCP 连接,那么 TCP 协议程序发送的就不是 FIN,而是 RST。此时会出现 Connection reset by peer 错误,详见下文测试代码。

  8. 请求超时后收到回复

    主机创建 socket,设置 SO_RCVTIMEOUT 选项为100ms,向对端发送 SYN,超过100ms后才收到 ACK+SYN,那么主机的协议栈会直接回复一个 RST。

  9. SO_LINGER

    socket 设置 SO_LINGER 选项,socket 调用 close 函数时,会直接丢弃缓冲区 Send_Q 未发完的数据,并发送 RST。

  10. Linux 下启用 TIME_WAIT 快速回收

    修改 /etc/sysctl.conf 中内核参数:net.ipv4.tcp_tw_recycle = 1,当收到的 SYN 包的 timestamp 比上次的小时,就会发 RST。

  11. 移动链路

    移动网络下,国内是有5分钟后就回收信令,也就是 IM 产品,如果心跳>5分钟后服务器再给客户端发消息,就会收到 RST。也要查移动网络下 IM 保持<5min 心跳。

  12. GFW

    防火长城(Great Firewall of China,简称GFW)是中国政府在互联网空间中发起的一项大规模干预措施,旨在审查并控制中国地区的互联网使用,以遏制虚假信息、不良内容和外部信息流入中国境内。防火长城被普遍认为是政府和监管机构利用技术工具监控国家居民上网行为的全球最大系统,而它的技术基础上,有多种关键的审查与监管工具,如域名解析服务(DNS)、网络流量检测和内容过滤系统(CFMS)等。

  13. 负载等设备

    负载设备需要维护连接转发策略,长时间无流量,连接也会被清除,而且很多都不告诉两层机器,新的包过来时才通告 RST。

    Apple push 服务也有这个问题,而且是不可预期的偶发性连接被 RST;RST 前第一个消息 write 是成功的,而第二条写才会告诉你连接被重置,

    曾经被它折腾没辙,因此打开每2秒一次 tcp keepalive,固定5分钟 TCP 连接回收,而且发现连接出错时,重发之前10s内消息。

  14. 超过超时重传次数

  15. seq 不正确

  16. keepalive 超时

    公网服务 tcp keepalive 最好别打开;移动网络下会增加网络负担,切容易掉线;非移动网络核心 ISP 设备也不一定都支持 keepalive,曾经也发现过广州那边有个核心节点就不支持。

  17. 数据错误,不是按照既定序列号发送数据

测试代码

  1. 上述第6种情况【TCP 接收缓冲区 Recv-Q 中的数据未完全被应用程序读取时关闭该 socket】

    客户端测试代码:

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdlib.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <string.h>
    #include <errno.h>
    #include <fcntl.h>int main(void)
    {int len;int sockFd;char sendBuf[256];struct sockaddr_in addr;bzero(&addr, sizeof(addr));addr.sin_family = AF_INET;inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);addr.sin_port = htons(8888);if ((sockFd = socket(AF_INET, SOCK_STREAM, 0)) < 0){perror("socket error");return -1;}if (connect(sockFd, (struct sockaddr *)&addr, sizeof(addr)) < 0){perror("connect error");close(sockFd);return -1;}memset(sendBuf, 0xFF, sizeof(sendBuf));send(sockFd, sendBuf, sizeof(sendBuf), 0);len = recv(sockFd, sendBuf, sizeof(sendBuf), 0);if (len >= 0){printf("len: %d\n", len);}else{printf("[line:%d] errno: %d, strerror(errno): %s\n", __LINE__, errno, strerror(errno));		}close(sockFd);return 0;
    }
    

    服务端测试代码:

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdlib.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <string.h>
    #include <errno.h>
    #include <fcntl.h>int main(void)
    {int readLen;int sockFd;int clientFd;char recvBuf[128] = {0};struct sockaddr_in saddr;if ((sockFd = socket(AF_INET, SOCK_STREAM, 0)) < 0){perror("socket error");return -1;}bzero((void*)&saddr, sizeof(saddr));saddr.sin_family = AF_INET;saddr.sin_addr.s_addr = htonl(INADDR_ANY);saddr.sin_port = htons(8888);if (bind(sockFd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0){perror("bind error");close(sockFd);return -1;}if (listen(sockFd, 5) < 0){perror("listen error");close(sockFd);return -1;}printf("accept waiting, sockFd: %d\n", sockFd);if ((clientFd = accept(sockFd, NULL, NULL)) == -1){perror("accept error");close(sockFd);return -1;}while (1){memset(recvBuf, 0, sizeof(recvBuf));readLen = recv(clientFd, recvBuf, sizeof(recvBuf), 0);if (readLen > 0){printf("readLen: %d\n", readLen);}else if (readLen == 0){printf("client fd is closed!\n");close(clientFd);break;}else {printf("[line:%d] errno: %d, strerror(errno): %s\n", __LINE__, errno, strerror(errno));close(clientFd);break;}close(clientFd);break;}close(sockFd);return 0;
    }
    

    服务端输出:
    在这里插入图片描述

    客户端输出:
    在这里插入图片描述

    wireshark 抓包结果:
    在这里插入图片描述

    该举例中,客户端发送256字节的数据到服务端,服务端只接收了128字节的数据就关闭了套接字,此时服务端的 TCP 接收缓冲区中还剩128字节未读取,所以服务端发送 RST 到客户端。

  2. 上述第5种情况【处理半打开连接】

    客户端测试代码:

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdlib.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <string.h>
    #include <errno.h>
    #include <fcntl.h>int main(void)
    {int len;int sockFd;char sendBuf[256];struct sockaddr_in addr;bzero(&addr, sizeof(addr));addr.sin_family = AF_INET;inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);addr.sin_port = htons(8888);if ((sockFd = socket(AF_INET, SOCK_STREAM, 0)) < 0){perror("socket error");return -1;}if (connect(sockFd, (struct sockaddr *)&addr, sizeof(addr)) < 0){perror("connect error");close(sockFd);return -1;}memset(sendBuf, 0xFF, sizeof(sendBuf));send(sockFd, sendBuf, sizeof(sendBuf), 0);sleep(1);send(sockFd, sendBuf, sizeof(sendBuf), 0);close(sockFd);return 0;
    }
    

    服务端测试代码:

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdlib.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <string.h>
    #include <errno.h>
    #include <fcntl.h>int main(void)
    {int readLen;int sockFd;int clientFd;char recvBuf[256] = {0};struct sockaddr_in saddr;if ((sockFd = socket(AF_INET, SOCK_STREAM, 0)) < 0){perror("socket error");return -1;}bzero((void*)&saddr, sizeof(saddr));saddr.sin_family = AF_INET;saddr.sin_addr.s_addr = htonl(INADDR_ANY);saddr.sin_port = htons(8888);if (bind(sockFd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0){perror("bind error");close(sockFd);return -1;}if (listen(sockFd, 5) < 0){perror("listen error");close(sockFd);return -1;}printf("accept waiting, sockFd: %d\n", sockFd);if ((clientFd = accept(sockFd, NULL, NULL)) == -1){perror("accept error");close(sockFd);return -1;}while (1){memset(recvBuf, 0, sizeof(recvBuf));readLen = recv(clientFd, recvBuf, sizeof(recvBuf), 0);if (readLen > 0){printf("readLen: %d\n", readLen);}else if (readLen == 0){printf("client fd is closed!\n");close(clientFd);break;}else {printf("[line:%d] errno: %d, strerror(errno): %s\n", __LINE__, errno, strerror(errno));close(clientFd);break;}close(clientFd);break;}close(sockFd);return 0;
    }
    

    wireshark 抓包结果: 在这里插入图片描述

    该举例中,客户端发送数据到服务端,服务端将数据接收后就关闭了套接字,随后,客户端又发送数据到服务端,因为此时服务端已将套接字关闭,所以服务端会发送 RST 到客户端。

参考

[1] https://zhuanlan.zhihu.com/p/361714600
[2] https://baijiahao.baidu.com/s?id=1632327385547303797&wfr=spider&for=pc
[3] https://www.cnblogs.com/JohnABC/p/6323046.html
[4] https://www.pianshen.com/article/8750375150/

相关文章:

TCP协议的RST标志

下文中的内容多数来自【参考】中的文章&#xff0c;这边进行一个整理和总结&#xff0c;后续会慢慢增加出现各个 RST 包的测试代码&#xff0c;便于理解。 TCP的 “断开连接” 标志 RST 标志 Reset&#xff0c;复位标志&#xff0c;用于非正常地关闭连接。它是 TCP 协议首部里…...

【软件质量与软件测试 白盒测试与黑盒测试】

第十章 黑盒测试 10.1 等价类划分&#xff1a; 10.1.1 划分等价类 等价类是指所有数据中的一组&#xff0c;它们具有相同的测试结果或相同的响应。等价类划分是将输入数据分为多个等价类的过程。 10.1.2 划分等价类的方法 划分等价类方法主要包括以下几种&#xff1a; 特…...

JavaScript教程(高级)

面向对象编程介绍 两大编程思想 &#xff08;1&#xff09;、 面向过程编程&#xff1a; &#xff08;缩写 POP&#xff09;&#xff08; Process-oriented programming&#xff09;面向过程就是分析出解决问题所需要的步骤&#xff0c;然后用函数把这些步骤一步一步实现&am…...

C++进阶 —— 范围for(C++11新特性)

目录 一&#xff0c;范围for介绍 二&#xff0c;范围for注意事项 一&#xff0c;范围for介绍 范围for&#xff08;range-based for loop&#xff09;是C11新引入的特性&#xff0c;可遍历各种序列结构的容器&#xff08;如数组、vector、list等&#xff09;&#xff1b;每次循…...

ELK +Filebeat日志分析系统

一、 ELK日志分析系统概述 1、ELK简介 ELK是三个开源软件的缩写&#xff0c;分别表示&#xff1a;Elasticsearch , Logstash, Kibana , 它们都是开源软件。新增了一个FileBeat&#xff0c;它是一个轻量级的日志收集处理工具(Agent)&#xff0c;Filebeat占用资源少&#xff0c…...

万字解析PELT算法!

Linux是一个通用操作系统的内核&#xff0c;她的目标是星辰大海&#xff0c;上到网络服务器&#xff0c;下至嵌入式设备都能运行良好。做一款好的linux进程调度器是一项非常具有挑战性的任务&#xff0c;因为设计约束太多了&#xff1a; 它必须是公平的快速响应系统的throughp…...

腾讯云服务器端口怎么全开?教程来了

腾讯云服务器端口怎么全开&#xff1f;云服务器CVM在安全组中设置开通&#xff0c;轻量应用服务器在防火墙中设置&#xff0c;腾讯云百科来详细说下腾讯云服务器端口全开放教程&#xff1a; 目录 腾讯云服务器端口全部开通教程 云服务器CVM端口全开放教程 轻量应用服务器开…...

深入理解Java虚拟机:JVM高级特性与最佳实践-总结-13

深入理解Java虚拟机&#xff1a;JVM高级特性与最佳实践-总结-13 Java内存模型与线程Java内存模型原子性、可见性与有序性先行发生原则 Java内存模型与线程 Java内存模型 原子性、可见性与有序性 Java内存模型是围绕着在并发过程中如何处理原子性、可见性和有序性这三个特征来…...

租售keysight E8257D 50G模拟信号发生器 销售/回收

是德&#xff08;Keysight&#xff09; E8257D 模拟信号发生器 Keysight E8257D (Agilent) PSG 模拟信号发生器提供业界领先的输出功率、电平精度和高达 67 GHz 的相位噪声性能&#xff08;工作频率可达 70 GHz&#xff09;。Agilent PSG 模拟信号发生器的高输出功率和卓越的电…...

【C++】什么是函数模板/类模板?

文章目录 一、函数模板1.什么是函数模板&#xff1f;2.函数模板格式3.函数模板原理4.函数模板实例化&#xff08;1&#xff09;隐式实例化&#xff08;2&#xff09;显示实例化 二.类模板1.类模板定义格式2.类模板的实例化 总结 一、函数模板 1.什么是函数模板&#xff1f; 函…...

为什么是ChatGPT引发了AI浪潮?

目录 BERT和GPT简介 BERT和GPT核心差异 GPT的优势 GPT的劣势 总结 随着近期ChatGPT的火热&#xff0c;引发各行各业都开始讨论AI&#xff0c;以及AI可以如何应用到各个细分场景。为了不被时代“抛弃”&#xff0c;我也投入了相当的精力用于研究和探索。但在试验的过程中&…...

批处理文件(.bat)启动redis及任何软件(同理)

批处理文件 每次从文件根目录用配置文件格式来启动redis太麻烦了 可以在桌面上使用批处理文件&#xff08;.bat&#xff09;启动Redis&#xff0c;请按照以下步骤进行操作&#xff1a; 打开文本编辑器&#xff0c;如记事本。 在编辑器中输入以下内容&#xff1a; 将文件保存…...

深度学习求解稀疏最优控制问题的并行化算法

稀疏最优控制问题 问题改编自论文An FE-Inexact Heterogeneous ADMM for Elliptic Optimal Control Problems with L1-Control Cost { min ⁡ y ( μ ) , u ( μ )...

牛客网项目—开发社区首页

视频连接&#xff1a;开发社区首页_哔哩哔哩_bilibili 代码地址&#xff1a;Community: msf begin 仿牛客论坛项目 (gitee.com) 本文是对仿牛客论坛项目的学习&#xff0c;学习本文之前需要了解Java开发的常用框架&#xff0c;例如SpringBoot、Mybatis等等。如果你也在学习牛…...

uniapp水文【uniapp】

文章目录 1、前言2、历史3、发展4、功能5、优缺点6、总结7、附录7.1、高频使用7.2、使用注意 1、前言 Uniapp是一种跨平台的移动应用开发框架&#xff0c;它允许开发者使用一套代码库&#xff0c;同时生成iOS、Android等多个平台的应用程序。这种技术方案可以大大降低开发成本…...

Java函数式接口

3 函数式接口 3.1 函数式接口概述 函数式接口&#xff1a;有且仅有一个抽象方法的接口 Java中的函数式编程体现就是Lambda表达式&#xff0c;所以函数式接口就是可以适用于Lambda使用的接口只有确保接口中有且仅有一个抽象方法&#xff0c; Java中的Lambda才能顺利地进行推导…...

安装libevent库

安装libevent库 yum install libevent libevent-devel 自动安装Memcached yum install memcached 源码安装 下载1.6.19版本 wget https://www.memcached.org/files/memcached-1.6.19.tar.gz &#xff08;若证书过期yum install -y ca-certificates) 解压源码 tar -zxvf…...

vue 截取字符串的方法

vue中的字符串方法&#xff0c;我目前使用最多的是下面两种方法&#xff0c;因为 vue的字符串方法支持断言操作。 1、 vue中截取字符串的方法如下&#xff1a; 2、 vue中截取字符串的方法&#xff0c;这个方法也是需要依赖于 vue库提供的支持。 3、 vue中截取字符串的方法&…...

可数集和不可数集

有限集和无限集 后继集 设 S S S是任一集合&#xff0c;称 S S ∪ { S } S^ S\cup \left\{ S\right\} SS∪{S}为 S S S的后继集 自然数集 自然数集 N \mathbb{N} N的归纳定义是&#xff1a; &#xff08;1&#xff09; ∅ ∈ N \empty \in \mathbb{N} ∅∈N &#xff08…...

<Linux>《Linux 之 ps 命令详解大全(含实用命令)》

《Linux 之 ps 命令详解大全&#xff08;含实用命令&#xff09;》 1 常用命令1.1 显示所有当前进程1.2 显示所有当前进程1.3 显示所有当前进程1.4 根据用户过滤进程1.5 根据 CPU 使用来升序排序1.6 根据用户过滤进程1.7 查询全10个使用cpu和内存最高的应用1.8 通过进程名和PID…...

Unity GPU Instancing 在 OpenGL ES 上的底层实现与失效排查

1. 为什么 GPU Instancing 不是“开个开关就完事”的功能很多人第一次在 Unity 里勾上Enable GPU Instancing复选框&#xff0c;跑起来发现 Draw Call 确实从 200 掉到了 30&#xff0c;就以为“Instancing 成功了”。结果一换设备、一改 Shader、一加个自定义光照&#xff0c;…...

React Props:深入解析组件间的数据传递

React Props:深入解析组件间的数据传递 在React中,组件间的数据传递是构建复杂应用的关键。Props(属性)是React组件间数据传递的主要方式,它允许父组件向子组件传递数据。本文将深入探讨React Props的概念、使用方法以及注意事项。 一、Props的概念 Props是React组件的…...

NotebookLM移动端体验全拆解(iOS/Android双端对比报告·仅限内测用户知晓的性能阈值)

更多请点击&#xff1a; https://kaifayun.com 第一章&#xff1a;NotebookLM移动端体验全景概览 NotebookLM 作为 Google 推出的基于用户自有文档构建的 AI 助手&#xff0c;其移动端&#xff08;iOS/Android&#xff09;已正式开放下载。该应用并非简单将网页版界面缩放适配…...

深度拆解:TypeScript 大神把 .claude 目录开源,18 个 Skill 是给 AI 编程踩刹车的工程纪律

2026 年 4 月底&#xff0c;Total TypeScript 创始人、TypeScript 社区教父级人物 Matt Pocock 干了一件挺简单的事——把他个人 .claude 目录下的全部 Agent Skills 开源了。仓库叫 mattpocock/skills&#xff0c;副标题只有一句话&#xff1a;Skills for Real Engineers。一个…...

如何在跨平台场景下实现高效远程桌面控制?BilldDesk Pro的现代化解决方案

如何在跨平台场景下实现高效远程桌面控制&#xff1f;BilldDesk Pro的现代化解决方案 【免费下载链接】billd-desk 基于Vue3 WebRTC Nodejs Flutter搭建的远程桌面控制、游戏串流 项目地址: https://gitcode.com/gh_mirrors/bi/billd-desk 在远程办公和技术支持日益普…...

Python机器学习模型部署实战:从训练到生产环境

Python机器学习模型部署实战&#xff1a;从训练到生产环境 引言 作为从Python转向Rust的后端开发者&#xff0c;我深刻体会到机器学习模型部署的重要性。一个优秀的模型如果不能成功部署到生产环境&#xff0c;其价值将大打折扣。本文将从实战角度出发&#xff0c;详细介绍Pyth…...

一次性掌握Mapbox地图开发框架

又到一年毕业季&#xff0c;春招已经基本结束&#xff0c;选择不考研直接就业的同学&#xff0c;如果5月还没拿到offer&#xff0c;接下来只能等暑期实习岗位&#xff0c;再晚一点就只能等秋招了。想找WebGIS相关的岗位&#xff0c;可以通过各种企业官方招聘网站、大众招聘平台…...

今年小满不一般,老辈农谚里藏着农事提醒

2026 年的小满节气在 5 月 21 日 8:36:28 交节&#xff0c;不少人说今年小满不一般&#xff0c;老辈农谚里总结了三个特点&#xff0c;对农事有不少参考意义。1. 白天小满&#xff0c;昼夜温差变化大“白天小满凉嗖嗖&#xff0c;晚上小满热死牛”这句农谚是说&#xff0c;如果…...

15万个科技岗位消失的真相

周四早上7点43分&#xff0c;我的手机震动了一下&#xff0c;是一位同行的消息——另一位我认识了五年的数据团队负责人。他管理的团队规模是我的两倍&#xff0c;所在的公司你一定听说过。 消息只有四个字&#xff1a;“你的人安全吗&#xff1f;” 我立刻明白他的意思。Met…...

别再手动复制粘贴了!ChatGPT原生PPT导出功能已上线(仅限Enterprise Tier),3大未公开API接口实测报告

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;ChatGPT原生PPT导出功能的架构演进与企业级定位 ChatGPT原生PPT导出功能并非简单集成第三方渲染库&#xff0c;而是OpenAI在模型服务层、内容生成中间件与文档编排引擎三者深度协同下构建的端到端能力。…...