1、定义:

RST表示复位,RST=1表示TCP中出现严重错误(由于主机崩溃或其它原因),必须释放连接。RST=1还可用来拒绝一个非法的报文段或拒绝打开一个连接。发送RST后不会再有正常的四分组终止序列(Unix网络编程so_linger选项)。

2、有三个条件可以产生RST:

*SYN到达某端口但此端口上没有正在监听的服务器(针对TCP而言,UDP则返回端口不可达ICMP错误)。
*TCP想取消一个已有连接(使用套接字SO_LINGER选项)。
*TCP接收了一个根本不存在的连接上的分节。

3、说明

RST报文段不会导致另一端产生任何响应,另一端不进行确认,收到RST的一段将终止该连接,并通知应用层连接复位。

RST会造成丢弃任何待发数据并立即发送复位报文段。正常终止连接是在所有排队数据都已经发送之后才发送FIN,正常情况下没有任何数据丢失(TCP/IP详解p187)

4、RST数据报文产生情况

其实在网络编程过程中,各种RST错误其实是比较难排查和找到原因的。因此我们需要在编程时尽可能规避不合理的操作,而导致的RST数据包,而分析那些真正有异常的RST数据包。下面我列出几种会出现RST的情况:

1 端口未打开

服务器程序端口未打开而客户端来连接。这种情况是最为常见和好理解的一种了。去telnet一个未打开的TCP的端口可能会出现这种错误。这个和操作系统的实现有关。在某些情况下,操作系统也会完全不理会这些发到未打开端口请求。

比如在下面这种情况下,主机241向主机114发送一个SYN请求,表示想要连接主机114的40000端口,但是主机114上根本没有打开40000这个端口,于是就向主机241发送了一个RST。这种情况很常见。特别是服务器程序core dump之后重启之前连续出现RST的情况会经常发生。

当然在某些操作系统的主机上,未必是这样的表现。比如向一台WINDOWS7的主机发送一个连接不存在的端口的请求,这台主机就不会回应。

2 请求超时

曾经遇到过这样一个情况:一个客户端连接服务器,connect返回-1并且error=EINPROGRESS。 直接telnet发现网络连接没有问题。ping没有出现丢包。用抓包工具查看,客户端是在收到服务器发出的SYN之后就莫名其妙的发送了RST。

比如像下面这样:

有89、27两台主机。主机89向主机27发送了一个SYN,表示希望连接8888端口,主机27回应了主机89一个SYN表示可以连接。但是主机27却很不友好,莫名其妙的发送了一个RST表示我不想连接你了。

后来经过排查发现,在主机89上的程序在建立了socket之后,用setsockopt的SO_RCVTIMEO选项设置了recv的超时时间为100ms。而我们看上面的抓包结果表示,从主机89发出SYN到接收SYN的时间多达110ms。(从15:01:27.799961到15:01:27.961886, 小数点之后的单位是微秒)。因此主机89上的程序认为接收超时,所以发送了RST拒绝进一步发送数据。

3 提前关闭

关于TCP,我想我们在教科书里都读到过一句话,'TCP是一种可靠的连接'。 而这可靠有这样一种含义,那就是操作系统接收到的来自TCP连接中的每一个字节,我都会让应用程序接收到。如果应用程序不接收怎么办?你猜对了,RST。

看两段程序:

//server.c
int main(int argc, char** argv)  
{  
    int listen_fd, real_fd;  
    struct sockaddr_in listen_addr, client_addr;  
    socklen_t len = sizeof(struct sockaddr_in);  
    listen_fd = socket(AF_INET, SOCK_STREAM, 0);  
    if(listen_fd == -1)  
    {  
        perror("socket failed   ");  
        return -1;  
    }  
    bzero(&listen_addr,sizeof(listen_addr));  
    listen_addr.sin_family = AF_INET;  
    listen_addr.sin_addr.s_addr = htonl(INADDR_ANY);  
    listen_addr.sin_port = htons(SERV_PORT);  
    bind(listen_fd,(struct sockaddr *)&listen_addr, len);  
    listen(listen_fd, WAIT_COUNT);  
    while(1)  
    {  
        real_fd = accept(listen_fd, (struct sockaddr*)&client_addr, &len);  
        if(real_fd == -1)  
        {  
            perror("accpet fail  ");  
            return -1;  
        }  
        if(fork() == 0)  
        {  
            close(listen_fd);  
            char pcContent[4096];
            read(real_fd,pcContent,4096);
            close(real_fd);  
            exit(0);              
        }  
        close(real_fd);  
    }     
    return 0;  
}

这一段是server的最简单的代码。逻辑很简单,监听一个TCP端口然后当有客户端来连接的时候fork一个子进程来处理。注意看的是这一段fork里面的处理:
每次只是读socket的前4096个字节,然后就关闭掉连接。

char pcContent[4096];
read(real_fd,pcContent,4096);
close(real_fd);

然后再看一下client的代码:

//client.c
int main(int argc, char** argv)  
{  
    int send_sk;  
    struct sockaddr_in s_addr;  
    socklen_t len = sizeof(s_addr);  
    send_sk = socket(AF_INET, SOCK_STREAM, 0);  
    if(send_sk == -1)  
    {  
        perror("socket failed  ");  
        return -1;  
    }  
    bzero(&s_addr, sizeof(s_addr));  
    s_addr.sin_family = AF_INET;

inet_pton(AF_INET,SER_IP,&s_addr.sin_addr);  
    s_addr.sin_port = htons(SER_PORT);  
    if(connect(send_sk,(struct sockaddr*)&s_addr,len) == -1)  
    {  
        perror("connect fail  ");  
        return -1;  
    }  
    char pcContent[5000]={0};
    write(send_sk,pcContent,5000);
    sleep(1);
    close(send_sk);
}

这段代码更简单,就是打开一个socket然后连接一个服务器并发送5000个字节。刚才我们看服务器的代码,每次只接收4096个字节,那么就是说客户端发送的剩下的4个字节服务端的应用程序没有接收到,服务器端的socket就被关闭掉,这种情况下会发生什么状况呢,还是抓包看一看。

前三行就是TCP的3次握手,从第四行开始看,客户端的49660端口向服务器的9877端口发送了5000个字节的数据,然后服务器端发送了一个ACK进行了确认,紧接着服务器向客户端发送了一个RST断开了连接。和我们的预期一致。

4 在一个已关闭的socket上收到数据

如果某个socket已经关闭,但依然收到数据也会产生RST。

代码如下:

客户端:

int main(int argc, char** argv)  
{  
    int send_sk;  
    struct sockaddr_in s_addr;  
    socklen_t len = sizeof(s_addr);  
    send_sk = socket(AF_INET, SOCK_STREAM, 0);  
    if(send_sk == -1)  
    {  
        perror("socket failed  ");  
        return -1;  
    }  
    bzero(&s_addr, sizeof(s_addr));  
    s_addr.sin_family = AF_INET;

inet_pton(AF_INET,SER_IP,&s_addr.sin_addr);  
    s_addr.sin_port = htons(SER_PORT);  
    if(connect(send_sk,(struct sockaddr*)&s_addr,len) == -1)  
    {  
        perror("connect fail  ");  
        return -1;  
    }  
    char pcContent[4096]={0};
    write(send_sk,pcContent,4096);
    sleep(1);
    write(send_sk,pcContent,4096);
    close(send_sk);
}

服务端:

int main(int argc, char** argv)  
{  
    int listen_fd, real_fd;  
    struct sockaddr_in listen_addr, client_addr;  
    socklen_t len = sizeof(struct sockaddr_in);  
    listen_fd = socket(AF_INET, SOCK_STREAM, 0);  
    if(listen_fd == -1)  
    {  
        perror("socket failed   ");  
        return -1;  
    }  
    bzero(&listen_addr,sizeof(listen_addr));  
    listen_addr.sin_family = AF_INET;  
    listen_addr.sin_addr.s_addr = htonl(INADDR_ANY);  
    listen_addr.sin_port = htons(SERV_PORT);  
    bind(listen_fd,(struct sockaddr *)&listen_addr, len);  
    listen(listen_fd, WAIT_COUNT);  
    while(1)  
    {  
        real_fd = accept(listen_fd, (struct sockaddr*)&client_addr, &len);  
        if(real_fd == -1)  
        {  
            perror("accpet fail  ");  
            return -1;  
        }  
        if(fork() == 0)  
        {  
            close(listen_fd);  
            char pcContent[4096];
            read(real_fd,pcContent,4096);
            close(real_fd);  
            exit(0);              
        }  
        close(real_fd);  
    }     
    return 0;  
}

客户端在服务端已经关闭掉socket之后,仍然在发送数据。这时服务端会产生RST。

5. GFW

防火长城(英文名称Great Firewall of China,简写为Great Firewall,缩写GFW),也称中国防火墙或中国国家防火墙,指中华人民共和国政府在其管辖因特网内部建立的多套网络审查系统的总称,包括相关行政审查系统。[1] 首要设计者为北京邮电大学原校长方滨兴,被称为“国家防火墙之父”

6. 移动链路

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

7. 负载等设备

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

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

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

8. SO_LINGER 应用强制使用rst 关闭

该选项会直接丢弃未发送完毕的send buffer,可能造成业务错误,慎用; 当然内网服务间http client 在收到应该时主动关闭,使用改选项,会节省资源。

  好像曾经测试过haproxy 某种配置下,会使用rst关闭连接,少了网络交互而且没有TIME_WAIT 问题

9. 超过超时重传次数、网络暂时不可达

10. TIME_WAIT 状态

  tw_recycle = 1 时,sync timestamps 比上次小时,会被rst

11. 非正常包

  连接已经关闭,seq 不正确等

12. keepalive 超时

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

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

wireshark 学习更进一步 之RST数据解读相关推荐

  1. wireshark 学习更进一步 之wireshark异常数据解读

    wireshark异常数据,软件本身会以特殊颜色底纹标识.或者可以通过Analyze-->Expert Information分析. 1.TCP Previous segment not cap ...

  2. 【深度学习】【物联网】深度解读:深度学习在IoT大数据和流分析中的应用

    作者|Natalie 编辑|Emily AI 前线导读:在物联网时代,大量的感知器每天都在收集并产生着涉及各个领域的数据.由于商业和生活质量提升方面的诉求,应用物联网(IoT)技术对大数据流进行分析是 ...

  3. 【深度学习】深度解读:深度学习在IoT大数据和流分析中的应用

    来源:网络大数据(ID:raincent_com) 摘要:这篇论文对于使用深度学习来改进IoT领域的数据分析和学习方法进行了详细的综述. 在物联网时代,大量的感知器每天都在收集并产生着涉及各个领域的数 ...

  4. 世界卫生日:大数据解读抑郁症群体

    4月7日是.今年世界卫生日关注的是抑郁症. 大数据解读抑郁症群体 据世界卫生组织统计数据显示,到2020年,抑郁症将成为仅次于心脏病的第二大疾病.目前全球有3亿多人正遭受抑郁症困扰.中国抑郁症的患病率 ...

  5. CTR深度学习模型之 DeepFM 模型解读

    CTR 系列文章: 广告点击率(CTR)预测经典模型 GBDT + LR 理解与实践(附数据 + 代码) CTR经典模型串讲:FM / FFM / 双线性 FFM 相关推导与理解 CTR深度学习模型之 ...

  6. yolov1-v5学习笔记及源码解读

    目录 深度学习网络分类 评价指标 原理 yolov1 yolov2 yolov3 yolov4 yolov5 源码解读(v3为例) 深度学习网络分类 深度学习经典检测方法 通常分为 two-stage ...

  7. 下一代面向知识的 BI 到底有何不同,从 nextionBI 数据解读能力中一探究竟

    2022年2月25日,nextionBI举办线上发布会,这是下一代BI首次正式与大众见面.nextionBI的定位是数据融合的增强分析型敏捷BI平台,面向知识设计,关注知识的积累.发现与应用.这一定位 ...

  8. 【云周刊】第125期:高考恢复40年!你们要的大数据解读来啦

    摘要: 恢复高考这40年发生了哪些变迁?看看大数据的解读吧:Kotlin成为 Android开发一级语言后,真的会取代JAVA吗:大牛又是如何复盘递归神经网络的呢--更多精彩技术资讯,下滑查看吧! 本 ...

  9. 【深度学习】从Pix2Code到CycleGAN:2017年深度学习重大研究进展全解读

    选自Statsbot 作者:Eduard Tyantov 机器之心编译 2017 年只剩不到十天,随着 NIPS 等重要会议的结束,是时候对这一年深度学习领域的重要研究与进展进行总结了.来自机器学习创 ...

最新文章

  1. mysql grant 不想让用户看到 系统默认 mysql_MYSQL用户权限管理GRANT使用
  2. Failed to bind properties under mybatis-plus.configuration.result-maps[0]
  3. netbsd配置gnome桌面
  4. 数据库的设计与连接、站点的搭建
  5. plt导致的_tkinter.TclError: no display name and no $DISPLAY environment variable的问题
  6. Oracle回收站解决误删除表
  7. Linux shell编程中read参数说明
  8. BootStrap的介绍与案例使用
  9. ccsk matlab,一种CCSK解调预处理方法与流程
  10. Mybiosource丨Mybiosource玻连蛋白 (VTN),ELISA 试剂盒原理
  11. golang 结构体使用chan
  12. 『杭电1726』God’s cutter
  13. python 豆瓣电影top250_Python数据可视化:豆瓣电影TOP250
  14. BZOJ 1189 HNOI2007 紧急疏散evacuate
  15. cvat标注软件入门
  16. 超强大的手机端logo设计制作软件免费分享!
  17. AE PR模板基本图形预设素材包动态字幕文字标题排版动画预设效果
  18. 华为接班人准备好了吗? (转载)
  19. 读论文《A Neural Probabilistic Language Model》
  20. python实现水滴筹页面的数据统计

热门文章

  1. vue 中哪些操作自动触发更新视图
  2. Mapreduce圳鹏数据
  3. 极客大学产品经理训练营:PRD 产品原型文档框架 第12课总结
  4. Python适合零基础入门吗?零基础学 Python 有什么建议?
  5. 阿里云/华为云云盘挂载步骤
  6. IHE测试系列之三:测试要求
  7. java生成gif_如何将视频转为gif制作有趣动图
  8. 以“国土资源云”统领国土资源信息化建设
  9. 让你的鼠标变为中指 - 浏览器插件The Finger Cursor
  10. python小游戏 2048小游戏设计与实现