TCP链接异常: SYN_RECV

news2024/11/12 20:52:02

1. 异常数据包分析:

从数据包分析来看应该是网关这边出问题了,应该是网关的服务程序在1217上出问题了,

(注意左右量变的数据包的一个syn的Seq都是1358143899)

 

从重发2开始网关这边就一直认为它没有收到client回复给它的ACK,但是从量变的数据包来看,client一直都有收到syn_ack, 并且也回复了每次的ACK到网关,网关的网口也有收到这个ACK,但是服务程序就是认为自己没有收到。图片的左边是tcpclient上的数据包,右边是网关上的数据包。

192.170.146.254是模拟hmi的电脑ip,192.170.146.5是网关的IP。出问题时重新从.254的pc上是可以ssh连接上网关的,开关网口也没有是hmi恢复正常(也有重启hmi的动作).

2 补充知识:

tcp的三次握手如下拖所示,也可以看到相关的状态机:

 

tcp完整状态机:

 

状态名称

含义

LISTEN

服务端需要打开一个socket进行监听,状态为LISTEN

SYN_SENT

客户端通过应用程序调用connect进行active open.于是客户端tcp发送一个SYN以请求建立一个连接.之后状态置为SYN_SENT(半链接)

SYN_RECV

服务端应发出ACK确认客户端的SYN,同时自己向客户端发送一个ACK. 之后状态置为SYN_RECV(半链接)

ESTABLISHED

代表一个打开的连接,双方可以进行或已经在数据交互了(全连接)

FIN_WAIT1

主动关闭(active close)端应用程序调用close,于是其TCP发出FIN请求主动关闭连接,之后进入FIN_WAIT1状态.等待远程TCP的连接中断请求,或先前的连接中断请求的确认

FIN_WAIT2

主动关闭端接到ACK后,就进入了FIN-WAIT-2

TIME_WAIT

在主动关闭端接收到FIN后,TCP就发送ACK包,并进入TIME-WAIT状态。等待足够的时间以确保远程TCP接收到连接中断请求的确认。(TIME_WAIT状态的形成只发生在主动关闭连接的一方)

CLOSE_WAIT

被动关闭(passive close)端TCP接到FIN后,就发出ACK以回应FIN请求(它的接收也作为文件结束符传递给上层应用程序),并进入CLOSE_WAIT. 等待从本地用户发来的连接中断请求(等待本地应用程序执行close)

LAST_ACK

被动关闭端一段时间后,接收到文件结束符的应用程序将调用CLOSE关闭连接。这导致它的TCP也发送一个 FIN,等待对方的ACK.就进入了LAST-ACK

CLOSING

比较少见,维持时间非常短,等待远程TCP对连接中断的确认

CLOSED

被动关闭端在接受到ACK包后,就进入了closed的状态,本地连接结束。

3. 项目代码(略)

4. 特别解释下面三种状态

SYN_RECV

服务端应发出ACK确认客户端的SYN,同时自己向客户端发送一个SYN. 之后状态置为SYN_RECV,等待客户端回应的ACK,触发accept()完成,如果accept没有完成,状态就会维持。

CLOSE_WAIT

被动关闭(passive close)端TCP接到FIN后,就发出ACK以回应FIN请求,但是网关还没有调用close()。比如出问题时,网关的很多连接应该会是这样。

TIME_WAIT

在主动关闭端接收到FIN后,TCP就发送ACK包,并进入TIME-WAIT状态。比如出问题时,HMI的很多连接应该会是这样。

5. 测试代码:

5.1 通过测试代码来控制tcp的流程,然后观察连接状态的变化,使用tcp助手作为client去连接下面的测试代码的8888端口,

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<unistd.h>
#include<arpa/inet.h>
#include <sys/time.h>
#include <unistd.h>

#define MAXLINE 25

int main(int argc, char** argv)
{
    int  listenfd, connfd;
    struct sockaddr_in  servaddr;
    char  buff[25];
    int  n,cnt=0,i;
    int res,ret;


        struct  timeval    tv1,tv2;


    if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){
        printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
        return 0;
    }



    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr =htonl(INADDR_ANY);
    servaddr.sin_port = htons(8888);
    int on = 1;

    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));


    if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){
        printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
        return 0;
    }

    if( listen(listenfd, 3) == -1){//控制sync队列的大小,方便测试
        printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
        return 0;
    }
        struct sockaddr_in cin;
        socklen_t addrlen = sizeof(cin);

        while(1) sleep(10);//故意不进入accept,让连接状态保持在SYN_RECV

        if((connfd = accept(listenfd,(struct sockaddr *)&cin,&addrlen)) < 0)
        {
            printf("accept err\n");
            exit(1);
        }

        char ipv4_addr[16];
        if(!inet_ntop(AF_INET,(void *)&cin.sin_addr,ipv4_addr,sizeof(cin)))
        {
            printf("inet_ntop\n");
            exit(1);
        }
        printf("Client(%s:%d) is connected!\n",ipv4_addr,htons(cin.sin_port));

    printf("======waiting for client's request======\n");
    while(1){
          cnt++;
                printf("%drecv msg from client:",cnt);
                memset(buff, 0, sizeof(buff));
                n = recv(connfd, buff, MAXLINE, 0);
                if(n > 0)
                    {
                        for(i = 0;i< n;i++)
                       printf("%c ", buff[i]);
                    }

            printf("\n");

            send(connfd, buff, n,MSG_NOSIGNAL);


    }
    close(connfd);
    close(listenfd);
    return 0;
}

5.2 测试代码测试分析如下:

在TCP的三次握手中,走后一个ACK已经从client端(PC侧)发到Service端(网关)的网口上了,但是网关的服务程序没有收到,所以网关的状态维持在SYN_RECV,并且协议栈开始重发SYN_ACK。这个行为和我们在现场抓的数据包的行为是一样的。

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Okhttp连接泄漏警告问题分析

背景 某天在查询生产日志时&#xff0c;发现大量的Okhttp连接泄漏警告日志&#xff0c;但生产上没有收到任何异常反馈。出于好奇心&#xff0c;本地最小化复现问题&#xff0c;并最终解决问题。 分析问题 okhttp官网的demo示例 OkHttpClient client new OkHttpClient();Stri…

【K8S】学习笔记(二)

K8S学习笔记三、Kubernetes 核心概念3.1、kubernetes 集群命令行工具 kubectl3.1.1、kubectl 概述3.1.2、kubectl 命令格式3.1.3、kubectl 基础命令3.1.4、kubectl 部署命令3.1.5、kubectl 集群管理命令3.1.6、kubectl 故障和调试命令3.1.7、kubectl 其它命令3.2、Kubernetes 集…

分组后将成员拼成字符串

【问题】 I have a text file like this: key1 value1 A key1 value2 B key1 value3 A key2 value1 A key2 value2 BI am trying to open it as a dictionary and print the list of keys and values separated by commas so it looks like this in the end: key1 value1,va…

PTA题目 谁先倒

划拳是古老中国酒文化的一个有趣的组成部分。酒桌上两人划拳的方法为&#xff1a;每人口中喊出一个数字&#xff0c;同时用手比划出一个数字。如果谁比划出的数字正好等于两人喊出的数字之和&#xff0c;谁就输了&#xff0c;输家罚一杯酒。两人同赢或两人同输则继续下一轮&…

智云通CRM:越是害怕被客户拒绝,你就越会被拒绝?

你害怕被客户拒绝码&#xff1f;先别急着说“害怕”&#xff0c;先来看看你为什么会被拒绝&#xff1f;因为你认为自己会失败&#xff01; 很多情况霞&#xff0c;我们会被客户拒绝&#xff0c;原因在哪里&#xff1f;原因有很多&#xff0c;最常见的是因为业务员自身的心理障…

SSM整合(四)

SSM整合之redis设置值和获取值三种方式 准备工作(导入一些必要的依赖) <dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-redis</artifactId><version>2.4.1</version> </dependency> <…

ES6 入门教程 19 Generator 函数的语法 19.1 简介

ES6 入门教程 ECMAScript 6 入门 作者&#xff1a;阮一峰 本文仅用于学习记录&#xff0c;不存在任何商业用途&#xff0c;如侵删 文章目录ES6 入门教程19 Generator 函数的语法19.1 简介19.1.1 基本概念19.1.2 yield 表达式19.1.3 与 Iterator 接口的关系19 Generator 函数的语…

Espressif-IDE ESP32 LED Flash 闪烁工程的创建

前言 Espressif-IDE 类似于 eclipse 开发环境&#xff0c;更新 ESP32的开发环境后&#xff0c;发现可以直接使用 Espressif-IDE 进行ESP32 的工程代码开发、程序下载&#xff0c;非常的方便 本篇开始把 ESP32的开发板的LED 点亮&#xff0c;熟悉下 Espressif-IDE 的开发流程 …

MySQL表的高级增删改查

文章目录一、聚合查询二、分组查询三、联合查询内连接外连接自连接四、合并查询五、子查询一、聚合查询 聚合查询是针对行与行之间的计算&#xff0c;常见的聚合函数有: 函数作用COUNT(expr)查询数据的数量SUM(expr)查询数据的总和AVG(expr)查询数据的平均值MAX(expr)查询数据…

ES6 入门教程 18 Iterator 和 for...of 循环 18.1 Iterator(遍历器)的概念

ES6 入门教程 ECMAScript 6 入门 作者&#xff1a;阮一峰 本文仅用于学习记录&#xff0c;不存在任何商业用途&#xff0c;如侵删 文章目录ES6 入门教程18 Iterator 和 for...of 循环18.1 Iterator&#xff08;遍历器&#xff09;的概念18 Iterator 和 for…of 循环 18.1 Iter…

zk中watcher机制(重补早期学习记录)

前言:补学习记录,几年前写一半丢草稿箱,突然看到,有强迫症所以补完 一、理解watcher机制 二、父节点watcher事件 连接zk客户端 ./zkCli.sh 使用help查看命令 父节点使用,stat或者get创建自己的watch事件 stat 路径 watch get 路径 watch 我们给一个不存在的节点设置一个w…

这次把怎么做好一个PPT讲清-动画篇

干货预警&#xff01; 作为一位PPT发烧友看过诸多PPT案例&#xff0c;分享几个高大上的动画效果。文末有福利&#xff01; 废话不多说&#xff0c;直接上重点&#xff0c;本文主要讲八个动画技巧&#xff0c;我们来看先目录&#xff1a; 收藏是点赞的六倍&#xff0c;各位看官…

统计学习、机器学习以及python的学习顺序是什么

前言 我是非科班出身成功转行算法的&#xff0c;我来说下我的学习路线是怎样的。&#xff08;文末送读者福利&#xff09; 1、看书学原理&#xff1a;我因为没买周志华老师的西瓜书&#xff0c;只看过李航老师的小蓝书&#xff0c;我第一遍看统计学习 方法的时候非常痛苦全是…

Monaco Editor教程(十七):代码信息指示器CodeLens配置详解

背景 有时候我们在使用VS Code编辑一个文件时 会看到这样的效果 在上述的图片中&#xff0c;1720行和1721行之间&#xff0c;有一行不属于该文件本身内容的注释。这一效果能够方便开发者快速地理解代码&#xff0c;看到代码的提交人&#xff0c;时间&#xff0c;可能还会有备…

C语言:一维数组的创建、初始化

一、一维数组的创建 数组的定义&#xff1a;在C语言中有各种数据类型&#xff0c;而每一种数据类型都有相对应的数据元素&#xff0c;这些元素可以组成一个团体&#xff0c;一个集合&#xff0c;从而有了数组概念。 数组也有三要素&#xff1a;数组元素类型&#xff0c; …

双链笔记Logseq的安装指南

便民服务还是挺方便的&#xff0c;不用出小区就可以做了 本文完成于 10 月初&#xff0c;撰写时 Logseq 的版本为 v0.8.8&#xff0c;发布时的最新版本是 v0.8.11 什么是 Logseq &#xff1f; Logseq 是一个本地优先的非线性大纲笔记本&#xff0c;用于组织和共享您的个人知识库…

Win11电脑如何设置自动开机(Windows 11 2022H2)

Win11电脑如何设置自动开机 ​ 文章目录1、最先右键选择“此电脑”&#xff0c;点一下“管理”。2、随后寻找系统工具里的“任务方案程序”。3、再点一下右边的“创建基本任务”。4、名字中输入“自动开机”。5、随后选择自动开机的次数。6、然后设置我们应该自动开机的实际时间…

并发编程之Executor线程池原理与源码解读

线程 线程是调度CPU资源的最小单位&#xff0c;线程模型分为KLT模型与ULT模型&#xff0c;JVM使用的KLT模 型&#xff0c;Java线程与OS线程保持1:1的映射关系&#xff0c;也就是说有一个java线程也会在操作系统里有一个对应的线程。Java线程有多种生命状态 NEW,新建 RUNNABLE,运…

分布式架构演进过程

分布式的前提&#xff0c;我们得有多台服务器&#xff0c;那么我们需要知道世界上第一台计算机的由来&#xff0c;而第一台计算机的参考模型就是冯诺依曼模型&#xff0c;为此奠定了所有的分布式都在围绕着这个模型里面的某一块或者相互之间模块进行打交道。 搞分布式又有什么意…

【计算机毕业设计】7.健身俱乐部会籍管理系统+vue

一、系统截图&#xff08;需要演示视频可以私聊&#xff09; 摘 要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的…