当全连接队列满了,tcp客户端收到服务端RST信令的模拟

2024-04-17 06:36

本文主要是介绍当全连接队列满了,tcp客户端收到服务端RST信令的模拟,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

当tcp服务端全连接队列满了后,并且服务端也不accept取出连接,客户端再次连接时,服务端能够看到SYN_RECV状态。但是客户端看到的是ESTABLISHED状态,所以客户端自认为成功建立了连接,故其写往服务端写数据,发现数据也确实写成功了。
但是后面等到服务端通过ACK+SYN告知客户端重新ACK时,发现此时客户端的业务数据已经到来了,故而认为出了问题,故重置连接。

对应的代码如下:

客户端:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>#define PORT 8888                                     //端口地址:8888
#define SERVER_IP "10.0.0.64"extern void process_conn_client(int s);int main(int argc,char *argv[])
{int s = 0;                                        //socket描述符struct sockaddr_in server_addr;                   //服务器地址结构int ret = 0;                                      //返回值char buf[1024] = {0};int i = 0;strcpy(buf, "hello world");/***  Step 2 : 建立套接字*/s = socket(AF_INET,SOCK_STREAM,0);                //创建一个AF_INET族的流类型socketif(s < 0)                                         //检查是否正常创建socket{perror("socket error\n");exit(EXIT_FAILURE);}/***  Step 3 : 设置服务器地址*/memset(&server_addr, 0, sizeof(server_addr));          //清零server_addr.sin_family = AF_INET;                 //设置地址族为AF_INETinet_pton(AF_INET, SERVER_IP, &(server_addr.sin_addr));server_addr.sin_port = htons(PORT);               //设置端口号/***  Step 4 : 将用户输入的字符串类型的IP地址转为整型*///inet_pton(AF_INET,argv[1],&server_addr.sin_addr);/***  Step 5 : 连接服务器*/ret = connect(s,(struct sockaddr*)&server_addr,sizeof(struct sockaddr));if(ret < 0){perror("connect error\n");printf("errno is %d\n", errno);exit(EXIT_FAILURE);}printf("connect succeed\n");//for(;;){//sleep(10000000);sprintf(buf, "hello world, %d", i);i++;ret = write(s,buf,strlen(buf)+1);if(ret < 0){printf("write failed, errno is %d\n", errno);}ret = read(s, buf, strlen(buf)+1);if(ret < 0){printf("read failed, errno is %d\n", errno);}}while(1)sleep(10);close(s);                                         //关闭连接
}

服务端:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>#define PORT 8888                                    //侦听端口地址:8888
#define BACKLOG 20                                    //侦听队列长度:2extern void process_conn_server(int s);              //服务器对客户端的处理:读取数据并发送响应字符int main(int argc,char *argv[])
{int ss = 0;                                      //ss = server socket = 服务器socket描述符int cs = 0;                                      //cs = client socket = 客户端socket描述符struct sockaddr_in server_addr;                  //服务器地址结构struct sockaddr_in client_addr;                  //客户端地址结构int ret = 0;                                     //返回值pid_t pid;//进程IDchar buffer[1024];ssize_t size = 0;/***  Step 2 : 建立套接字*/ss = socket(AF_INET,SOCK_STREAM,0);              //创建一个AF_INET族的流类型socketif(ss < 0)                                       //检查是否正常创建socket{perror("socket error\n");exit(EXIT_FAILURE);}/***  Step 3 : 设置服务器地址*  Note:*      htonl():将主机数转换成无符号长整型的网络字节顺序*      htons():将整型变量从主机字节顺序转变成网络字节顺序*/bzero(&server_addr,sizeof(server_addr));          //清零server_addr.sin_family = AF_INET;                 //设置地址族为AF_INETserver_addr.sin_addr.s_addr = htonl(INADDR_ANY);  //本地地址server_addr.sin_port = htons(PORT);               //设置端口号/***  Step 4 : 绑定地址结构到套接字描述符*/ret = bind(ss,(struct sockaddr*)&server_addr,sizeof(server_addr));if (ret < 0)                                      //出错{perror("bind error\n");exit(EXIT_FAILURE);}/***  Step 5 : 设置侦听,侦听队列长度为2,可同时处理两个客户端连接请求*/ret = listen(ss,BACKLOG);if (ret < 0)                                      //出错{perror("bind error\n");exit(EXIT_FAILURE);}/***  Step 6 : 主循环过程*/sleep(6000);for(;;){/* 接收客户端连接 */int addrlen = sizeof(struct sockaddr);cs = accept(ss,(struct sockaddr*)&client_addr,&addrlen);if(cs < 0)                                    //出错{continue;                                 //结束本次循环}//sleep(30);/*for(;;){size = read(cs,buffer,1024);                 //从套接字中读取数据放到缓冲区buffer中if(size == 0)                               //没有数据{return;}printf("buffer is %s\n", buffer);}
*/}return 0;
}

客户端通过下面脚本并发投递100个:

#!/bin/bashfor i in {1..100}
do
{./tcpclient &
}
done

最终可以看到客户端的打印情况:
在这里插入图片描述
其中104代表连接被对端重置。

这篇关于当全连接队列满了,tcp客户端收到服务端RST信令的模拟的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/911044

相关文章

SpringBoot集成redisson实现延时队列教程

《SpringBoot集成redisson实现延时队列教程》文章介绍了使用Redisson实现延迟队列的完整步骤,包括依赖导入、Redis配置、工具类封装、业务枚举定义、执行器实现、Bean创建、消费... 目录1、先给项目导入Redisson依赖2、配置redis3、创建 RedissonConfig 配

java.sql.SQLTransientConnectionException连接超时异常原因及解决方案

《java.sql.SQLTransientConnectionException连接超时异常原因及解决方案》:本文主要介绍java.sql.SQLTransientConnectionExcep... 目录一、引言二、异常信息分析三、可能的原因3.1 连接池配置不合理3.2 数据库负载过高3.3 连接泄漏

RabbitMQ 延时队列插件安装与使用示例详解(基于 Delayed Message Plugin)

《RabbitMQ延时队列插件安装与使用示例详解(基于DelayedMessagePlugin)》本文详解RabbitMQ通过安装rabbitmq_delayed_message_exchan... 目录 一、什么是 RabbitMQ 延时队列? 二、安装前准备✅ RabbitMQ 环境要求 三、安装延时队

Mac电脑如何通过 IntelliJ IDEA 远程连接 MySQL

《Mac电脑如何通过IntelliJIDEA远程连接MySQL》本文详解Mac通过IntelliJIDEA远程连接MySQL的步骤,本文通过图文并茂的形式给大家介绍的非常详细,感兴趣的朋友跟... 目录MAC电脑通过 IntelliJ IDEA 远程连接 mysql 的详细教程一、前缀条件确认二、打开 ID

Go语言连接MySQL数据库执行基本的增删改查

《Go语言连接MySQL数据库执行基本的增删改查》在后端开发中,MySQL是最常用的关系型数据库之一,本文主要为大家详细介绍了如何使用Go连接MySQL数据库并执行基本的增删改查吧... 目录Go语言连接mysql数据库准备工作安装 MySQL 驱动代码实现运行结果注意事项Go语言执行基本的增删改查准备工作

python连接sqlite3简单用法完整例子

《python连接sqlite3简单用法完整例子》SQLite3是一个内置的Python模块,可以通过Python的标准库轻松地使用,无需进行额外安装和配置,:本文主要介绍python连接sqli... 目录1. 连接到数据库2. 创建游标对象3. 创建表4. 插入数据5. 查询数据6. 更新数据7. 删除

在 Spring Boot 中连接 MySQL 数据库的详细步骤

《在SpringBoot中连接MySQL数据库的详细步骤》本文介绍了SpringBoot连接MySQL数据库的流程,添加依赖、配置连接信息、创建实体类与仓库接口,通过自动配置实现数据库操作,... 目录一、添加依赖二、配置数据库连接三、创建实体类四、创建仓库接口五、创建服务类六、创建控制器七、运行应用程序八

Linux之UDP和TCP报头管理方式

《Linux之UDP和TCP报头管理方式》文章系统讲解了传输层协议UDP与TCP的核心区别:UDP无连接、不可靠,适合实时传输(如视频),通过端口号标识应用;TCP有连接、可靠,通过确认应答、序号、窗... 目录一、关于端口号1.1 端口号的理解1.2 端口号范围的划分1.3 认识知名端口号1.4 一个进程

解决hive启动时java.net.ConnectException:拒绝连接的问题

《解决hive启动时java.net.ConnectException:拒绝连接的问题》Hadoop集群连接被拒,需检查集群是否启动、关闭防火墙/SELinux、确认安全模式退出,若问题仍存,查看日志... 目录错误发生原因解决方式1.关闭防火墙2.关闭selinux3.启动集群4.检查集群是否正常启动5.

在Linux系统上连接GitHub的方法步骤(适用2025年)

《在Linux系统上连接GitHub的方法步骤(适用2025年)》在2025年,使用Linux系统连接GitHub的推荐方式是通过SSH(SecureShell)协议进行身份验证,这种方式不仅安全,还... 目录步骤一:检查并安装 Git步骤二:生成 SSH 密钥步骤三:将 SSH 公钥添加到 github