百万连接实现02:使用epoll实现的服务器

news2024/11/13 9:24:01

使用的操作系统:

t$ cat /proc/version 
Linux version 4.19.260 (lkmao@ubuntu) (gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.12)) #1 SMP Thu Sep 29 14:19:07 CST 2022

文件句柄的限制

如果不修改连接测试,会报错

一个tcp连接就需要占用一个文件描述符,一旦文件描述符用完,新的连接就会返回给我们错误是:Can’topen so many files。linux系统出于安全角度的考虑,在多个位置都限制了可打开的文件描述符的数量,包括系统级、进程级、用户进程级。

查看某个进程使用文件描述符

lsof -p 进程id |wc -l  //文件数量
ls /proc/进程id/fd |wc -l  //文件描述符数量

通过ulimit -n 查看一个进程的最多打开个数。

lkmao@ubuntu:~$ ulimit -n
1024
lkmao@ubuntu:~$

修改文件,在该文件尾部添加如下内容:因为要做百万连接测试,所以设置的很大。

sudo tee -a /etc/security/limits.conf << EOF

# 
* soft nofile 1020480
* hard nofile 1020480
* soft nproc 1020480
* hard nproc 1020480
EOF

然后重启系统,重新查询

貌似设置成功了。

 epoll服务器:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <fcntl.h>

// #define _DEBUG_INFO
#ifdef _DEBUG_INFO
#define DEBUG_INFO(format, ...) printf("%s:%s:%d -- "format"\n" \
,__FILE__,__func__,__LINE__ \
, ##__VA_ARGS__)
#else
#define DEBUG_INFO(format, ...)
#endif

#define _DEBUG_PRINT
#ifdef _DEBUG_PRINT
#define DEBUG_PRINT(format,...)	printf(format,##__VA_ARGS__)	
#else
#define DEBUG_PRINT(format,...)
#endif

//#define _DEBUG_CORE
#ifdef _DEBUG_CORE
#define DEBUG_CORE(format, ...) printf("%s:%s:%d -- "format"\n" \
,__FILE__,__func__,__LINE__ \
, ##__VA_ARGS__)
#else
#define DEBUG_CORE(format, ...)
#endif
int client_count = 0;
void sig_func(int sig){
    DEBUG_INFO("client_count = %d\n",client_count);
    sleep(1);
    exit(0);
}

struct epoll_event evlist[100000];
static char buf[1024 + 1];

int main(int argc, char **argv)
{
    int server_socket = 0;
    int epfd;
    int res = 0;
    struct epoll_event ev;
    
    int disconnect_client_count = 0;
    signal(SIGINT,sig_func);
    int on = 1;
   
    epfd = epoll_create(1);
    if(epfd < 0){
        perror("epoll_create");
        return -1;
    }
    server_socket = socket(PF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
    if(server_socket == -1){
        perror("socket");
        exit(1);
    }

    if(setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR,&on,sizeof(on)) < 0){
        perror("setsockopt");
        exit(-1);
    }
    struct sockaddr_in server_addr;
    server_addr.sin_port = htons(6600);
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("192.168.0.11");

    res = bind(server_socket,(const struct sockaddr *)&server_addr,sizeof(server_addr));
    if(res == -1){
        perror("bind");
        return -1;
    }
    res = listen(server_socket,5);
    if(res == -1){
        perror("listen");
        return -1;
    }

    ev.data.fd = server_socket;
    ev.events = EPOLLIN;
    epoll_ctl(epfd,EPOLL_CTL_ADD,server_socket,&ev);

    DEBUG_INFO("listen:%d",6600);

    int flags = 0;
    flags = fcntl(server_socket, F_GETFL);
    flags |= O_NONBLOCK;
    fcntl(server_socket, F_SETFL, flags);

    while(1){
        int ready = epoll_wait(epfd,evlist,sizeof(evlist)/sizeof(evlist[0]),-1);
        if(ready == -1){
            if(errno == EINTR){
                continue;
            }
            perror("epoll_wait");
            exit(1);
        }
        DEBUG_INFO("ready %d",ready);
        for(int i=0;i<ready;i++){
            int fd = evlist[i].data.fd;
            if(fd == server_socket){
                client_count++;
                socklen_t addrlen;
                struct sockaddr_in clientaddr;
                int newfd;
                addrlen = sizeof(clientaddr);
                memset(&clientaddr, 0, sizeof(clientaddr));
                newfd = accept(server_socket, (struct sockaddr *) &clientaddr, &addrlen);
                if (newfd == -1) {
                    perror("Server accept() error");
                } else {
                    ev.events = EPOLLIN;
                    ev.data.fd = newfd;
                    res = epoll_ctl(epfd,EPOLL_CTL_ADD,newfd,&ev);
                    if(res == -1){
                        perror("epoll_ctl EPOLL_CTL_ADD");
                        DEBUG_INFO("epoll_ctl EPOLL_CTL_ADD error");
                        exit(-1);
                    }
                    
                    DEBUG_INFO("New connection from %s:%d on socket %d\n",
                           inet_ntoa(clientaddr.sin_addr),
                           clientaddr.sin_port,
                           newfd);
                    DEBUG_CORE("client_count = %d\n", client_count);
                    if(client_count %10 == 0){
                        DEBUG_PRINT("client_count = %d\n", client_count);
                    }
                }
                continue;
            }
            DEBUG_INFO("fd = %d:events:%s %s %s",fd,
                        (evlist[i].events & EPOLLIN)?"EPOLLIN":"",
                        (evlist[i].events & EPOLLHUP)?"EPOLLHUP":"",
                        (evlist[i].events & EPOLLERR)?"EPOLLERR":"");
            int read_len = read(fd,buf,sizeof(buf) - 1);
            if(read_len == -1){
                if(errno == EINTR){
                    continue;
                }else{
                    perror("Read");
                    close(fd);
                    client_count--;
                    DEBUG_CORE("client_count = %d\n", client_count);
                    disconnect_client_count++;
                    DEBUG_PRINT("disconnect_client_count = %d\n", disconnect_client_count);
                    continue;
                }
            }
            DEBUG_INFO("read_len: %d",read_len);
            if(read_len == 0){
                DEBUG_INFO("client disconnected");
                close(fd);
                client_count--;
                DEBUG_CORE("client_count = %d\n", client_count);
                disconnect_client_count++;
                DEBUG_PRINT("disconnect_client_count = %d\n", disconnect_client_count);
                continue;
            }
            buf[read_len] = '\0';
            DEBUG_INFO("buf = %s",buf);
        }
    }
OUT:
    DEBUG_INFO("bye bye");
    return 0;
}

4万连接实验

使用前一章写的客户端。

./_build_/client -c 1000 -t 40 -r 192.168.0.11

为了使实验快一点,创建4万个连接,实际上也花了十几分钟呢。

 

说好的百万连接呢,怎么才测了4万,花时间太久了,下次优化一下,让测试快一点。

小结

为什么会这么慢呢?因为客户端虽然是多线程,但是加了互斥锁,为什么加互斥锁呢?因为在测试过程中,如果不加锁,总是会丢失连接,但是又没有报错。

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

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

相关文章

北京大学2015计算机学科夏令营上机考试

目录 A:整数的个数 B:过滤多余的空格 C:二维数组右上左下遍历 D 合影效果 E:Simple prefix compression【做不起】 F:To Europe! To Europe!【做不起】 G:The Game【做不起】 H:Falling Leaves A:整数的个数 #include<iostream> using namespace std; int main(…

VSCode 免安装及中文设置

前言&#xff1a;VSCode作为目前最强大的文本编辑器&#xff0c;通过内部的插件市场可满足各种开发需求。使用免安装版可以自定义插件安装位置等&#xff0c;而使用安装包安装只能通过修改快捷方式自定义&#xff0c;十分不方便。因此这里分享如何安装免安装版的VSCode。 下载…

ETL是什么?怎样更快的学习ETL?

ETL是英文Extract-Transform-Load的缩写&#xff0c;用来描述将数据从源端经过抽取(extract)、转换(transform)、加载(load)至目的端的过程&#xff0c;它能够对各种分布的、异构的源数据(如关系数据)进行抽取&#xff0c;按照预先设计的规则将不完整数据、重复数据以及错误数据…

滤波后点云的个数和之前相同,只是有的点云坐标是nan

进行点云的条件滤波&#xff0c;滤波前后点云的个数不变&#xff0c;只是被滤掉的点坐标显示为nan。代码片段如下&#xff1a; pcl::ConditionAnd<pcl::PointXYZ>::Ptr range_cond(new pcl::ConditionAnd<pcl::PointXYZ>()); range_cond->addComparison(pcl::Fi…

李宏毅transformer讲解;B站内测“搜索AI助手”功能

&#x1f989; AI新闻 &#x1f680; B站内测“搜索AI助手”功能 摘要&#xff1a;据反馈&#xff0c;B站正在内测“搜索 AI 助手”功能。用户在搜索框内输入问句或在搜索词中添加“?”即可体验此新功能。截图显示&#xff0c;该功能会为用户的搜索提供一个生成的答案&#…

hcip作业二

实验要求&#xff1a; 要求&#xff1a;R1-R2-R3-R4-R5 RIP 100运行版本2&#xff1b;R6-R7 RIP 200 运行版本1 1.使用合理IP地址规划网络&#xff0c;各自创建环回接口 2.R1创建环回 172.16.1.1/24 172.16.2.1/24 172.16.3.1/24 3.要求R3使用R2访问R1环回 4.减少路由条目数量&…

盘点一个Python网络爬虫抓取股票代码问题(上篇)

点击上方“Python爬虫与数据挖掘”&#xff0c;进行关注 回复“书籍”即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 去来江口守空船&#xff0c;绕船月明江水寒。 大家好&#xff0c;我是皮皮。 一、前言 前几天在Python白银群【厚德载物】问了一个Python网络爬虫的问题…

新手入门深度学习 | 3-2:激活函数activation

一、什么是激活函数 生物神经网络启发了人工神经网络(ANN)的发展。但是,人工神经网络并非大脑运作的近似表示。不过在我们了解为什么在人工神经网络中使用激活函数之前,先了解生物神经网络与激活函数的相关性是很有用处的。 典型神经元的物理结构包括细胞体(cell body)、…

软件的兼容性测试确保良好稳定运行的用户体验

在数字化时代&#xff0c;各种软件应用的开发和推广越来越普遍。然而&#xff0c;由于不同的操作系统、不同的设备配置和不同的软件版本&#xff0c;软件的兼容性成为了一个重要的问题&#xff0c;可以说软件的兼容性测试确保良好稳定运行的用户体验。 首先&#xff0c;软件的兼…

MySQL Optimization Learning(三)

一、通过索引进行优化 数据结构 Data Structure Visualizations 数据可视化效果展示 Binary Search Tree 插入数据可视化效果展示 AVL Tree Red/Black Tree --MYISAM存储引擎数据和引用分开存储 DROP TABLE IF EXISTS t_test; CREATE TABLE t_test (id int(11) NOT NULL,…

websocket 发送的消息超过默认限制就会自动断开连接

springboot集成websocket需要三步&#xff1a; 添加依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version>2.1.6.RELEASE</version></dependency>…

【GIT】Git常用命令学习

Git常用命令学习 说明&#xff1a;<>表示占位符的说明&#xff0c;[]表示可选&#xff0c;/表示“或” 仓库操作 初始化创建一个本地仓库 git init克隆远程仓库至本地 git clone <远程仓库地址> [仓库名称] #可以加上自定义仓库名称配置仓库 git config user.name…

Linux的动静态库

动静态库 1. 见一见动静态库2. 动静态库概念2.1 为什么要有动静态库2.2 定义 3. 写一写——库的设计角度打包成静态库打包成动态库 4. 用一用——使用者角度4.1 直接使用头文件和源文件&#xff08;直接给源代码&#xff09;4.2 得到头文件和源文件进过处理后形成的二进制文件.…

C++ - 20230703

一. 思维导图 二.练习 全局变量&#xff0c;int monster 10000;定义英雄类hero&#xff0c;受保护的属性string name&#xff0c;int hp,int attck&#xff1b;公有的无参构造&#xff0c;有参构造&#xff0c;虚成员函数 void Atk(){blood-0;}&#xff0c;法师类继承自英雄类…

SpringCloud:微服务技术

一、认识微服务&#xff1a; 首先&#xff0c;微服务架构不等于SpringCloud&#xff0c;微服务架构是一种经过良好架构设计的分布式架构方案&#xff0c; &#xff0c;它将应用构建成一系列按业务领域划分模块的&#xff0c;小的自治服务&#xff0c;并解决服务拆分所产生的各种…

css基础知识十五:如果要做优化,CSS提高性能的方法有哪些?

一、前言 每一个网页都离不开css&#xff0c;但是很多人又认为&#xff0c;css主要是用来完成页面布局的&#xff0c;像一些细节或者优化&#xff0c;就不需要怎么考虑&#xff0c;实际上这种想法是不正确的 作为页面渲染和内容展现的重要环节&#xff0c;css影响着用户对整个…

DL环境安装之GCC9,Python9与IDE连接远程环境:python notebook,解释器,C toolchain

文章目录 一.安装gcc91. 设置x86 centos7 yum源2. 编译安装 二、安装python3.91.前置依赖2. 编译安装3.建立软连接或环境变量 三、IDE连接远程环境1.IDE 远程notebook2.IDE 远程Python解释器3.远程toolchain &#xff08;后续可能有用&#xff09; 一.安装gcc9 系统自带的cc可…

2023亚马逊云科技中国峰会——Amazon DeepRacer

1.DeepRacer技术背景 早在20世纪初汽车问世之时&#xff0c;发明家们便已提出无人驾驶的设想。但即便是实现无人驾驶的初级阶段&#xff0c;也经历了足足百年时间。毕竟在复杂的城市路况下&#xff0c;机器若想像人一样实现感知、决策、控制等功能&#xff0c;必定面临各种复杂…

Simulink仿真模块 - Product

Product:标量和非标量的乘除运算或者矩阵的乘法和逆运算 库:Simulink / Commonly Used Blocks Simulink / Math Operations HDL Coder / Commonly Used Blocks HDL Coder / HDL Floating Point Operations HDL Coder / Math Operations 模型为: 双击模型打开参数设置界面为…