当前位置: 首页 > 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…...

用快马AI十分钟搞定数据库课程设计原型:学生选课系统从ER图到可运行Demo

今天想和大家分享一个超实用的数据库课程设计经验——如何用InsCode(快马)平台快速搭建学生选课系统原型。作为计算机专业学生&#xff0c;每次做数据库课设最头疼的就是从零开始写代码&#xff0c;但这次我发现了一个超级省时的方法。 ER图设计思路 首先需要明确系统核心实体&…...

SPM12实战:手把手教你搞定fMRI数据预处理(从时间矫正到空间平滑)

SPM12实战&#xff1a;零基础入门fMRI数据预处理全流程解析 第一次接触功能磁共振成像&#xff08;fMRI&#xff09;数据分析时&#xff0c;面对SPM12复杂的界面和晦涩的术语&#xff0c;很多新手都会感到无从下手。这篇文章将带你从零开始&#xff0c;用最直观的方式掌握fMRI数…...

手把手搭建基于Kintex UltraScale+的Cameralink图像处理系统:从LVDS解码到GTY输出HDMI的完整Vivado工程解析

手把手搭建基于Kintex UltraScale的Cameralink图像处理系统&#xff1a;从LVDS解码到GTY输出HDMI的完整Vivado工程解析 在工业视觉和医疗影像领域&#xff0c;Cameralink接口凭借其高带宽和低延迟特性&#xff0c;依然是许多高端相机的首选接口方案。而Xilinx的Kintex UltraSca…...

Z-Image-Turbo-辉夜巫女显存优化技巧:在低配置GPU上运行大模型的实战方法

Z-Image-Turbo-辉夜巫女显存优化技巧&#xff1a;在低配置GPU上运行大模型的实战方法 你是不是也遇到过这种情况&#xff1a;看到一个效果很棒的图像生成模型&#xff0c;比如Z-Image-Turbo-辉夜巫女&#xff0c;兴冲冲地准备跑起来试试&#xff0c;结果一运行就提示“CUDA ou…...

小白也能懂:将SPIRAN ART SUMMONER图像生成API封装成IDEA插件

小白也能懂&#xff1a;将SPIRAN ART SUMMONER图像生成API封装成IDEA插件 1. 为什么需要这个插件&#xff1f; 作为一名开发者&#xff0c;我经常遇到这样的场景&#xff1a;正在编写游戏角色设定文档时&#xff0c;突然需要一张概念图&#xff1b;设计UI界面时&#xff0c;想…...

Vue2项目实战:集成西瓜播放器xgplayer实现企业级视频播放组件

1. 为什么选择xgplayer做企业级视频播放方案 在在线教育平台这类对视频播放要求较高的场景中&#xff0c;播放器的选择直接影响用户体验和开发效率。我经历过多个项目的实战验证&#xff0c;西瓜播放器xgplayer确实是个不错的选择。它不像某些开源播放器那样需要折腾各种兼容性…...

给RV1126开发板写个‘WiFi管家’:一个脚本搞定连接、断开、状态查看与网络切换

RV1126开发板WiFi管家&#xff1a;打造智能网络管理工具链 在嵌入式开发领域&#xff0c;效率工具的价值往往被严重低估。想象一下这样的场景&#xff1a;当你需要在RV1126开发板上频繁切换测试环境、调试不同AP配置时&#xff0c;每次都要手动输入一长串命令&#xff0c;不仅…...

解锁AI编程新范式:Continue插件的颠覆性开发体验

解锁AI编程新范式&#xff1a;Continue插件的颠覆性开发体验 【免费下载链接】continue ⏩ Source-controlled AI checks, enforceable in CI. Powered by the open-source Continue CLI 项目地址: https://gitcode.com/GitHub_Trending/co/continue 你是否曾在深夜调试…...

合肥工业大学LaTeX学位论文模板零基础入门:高效解决方案与实战指南

合肥工业大学LaTeX学位论文模板零基础入门&#xff1a;高效解决方案与实战指南 【免费下载链接】HFUT_Thesis LaTeX Thesis Template for Hefei University of Technology 项目地址: https://gitcode.com/gh_mirrors/hf/HFUT_Thesis 在学术写作中&#xff0c;格式规范的…...

cool-admin(midway版)后端日志管理:日志聚合与集中式存储终极指南

cool-admin(midway版)后端日志管理&#xff1a;日志聚合与集中式存储终极指南 【免费下载链接】cool-admin-midway &#x1f525; cool-admin(midway版)一个很酷的后台权限管理框架&#xff0c;模块化、插件化、CRUD极速开发&#xff0c;永久开源免费&#xff0c;基于midway.js…...