测试Linux下tcp最大连接数限制

摘要:
=Nil{14fmt.Printf15return16}1718用于{19time.Sleep20}21}2223funmain(){24count:=025用于{26goConnect27count++;28fmt.Printf29time.Sleep30}31}注意:博客园区的代码编辑器尚未支持go。现在有很多人使用围棋。我希望尽快支持它。

现在做服务器开发不加上高并发根本没脸出门,所以为了以后吹水被别人怼“天天提高并发,你自己实现的最高并发是多少”的时候能义正言辞的怼回去,趁着元旦在家没事决定自己写个demo搞一搞。

这个测试主要是想搞明白Linux下哪些参数配置限制了连接数的最大值,上限是多少。

一、先说下demo的思路:

服务端用epoll实现,就是简简单单的接收连接,然后客户端用go的goroutine,每个goroutine就是简单的建立连接,然后什么也不做。

上代码:

server:

  1 /*
  2  * g++ -o test_epoll ./test_epoll.c
  3  */
  4 #include <unistd.h>
  5 #include <sys/types.h>
  6 #include <sys/socket.h>
  7 #include <sys/epoll.h>
  8 #include <netinet/in.h>
  9 #include <arpa/inet.h>
 10 
 11 #include <stdio.h>
 12 #include <stdlib.h>
 13 #include <string.h>
 14 #include <errno.h>
 15 
 16 int SetReuseAddr(int fd)
 17 {
 18     int optval = 1;
 19     socklen_t optlen = sizeof(optval);
 20     return setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, optlen);
 21 }
 22 
 23 int main()
 24 {
 25     int fd = socket(AF_INET, SOCK_STREAM, 0);
 26     int iRet = SetReuseAddr(fd);
 27     if (iRet != 0)
 28     {
 29         printf("setsockopt for SO_REUSEADDR failed, error:%s
", strerror(iRet));
 30         return iRet;
 31     }
 32 
 33     struct sockaddr_in addr;
 34     memset(&addr, 0, sizeof(addr));
 35     addr.sin_family = AF_INET;
 36     addr.sin_port = htons(8080);
 37     addr.sin_addr.s_addr = INADDR_ANY;
 38     if (bind(fd, (struct sockaddr*)&addr, sizeof(addr))  == -1)
 39     {
 40         printf("bind failed, error:%s
", strerror(errno));
 41         return errno;
 42     }
 43 
 44     if (listen(fd, 5) == -1)
 45     {
 46         printf("listen failed, error:%s
", strerror(errno));
 47         return errno;
 48     }
 49     printf("Listening on 8080...
");
 50 
 51     int epfd = epoll_create(102400);
 52     struct epoll_event event;
 53     event.events = EPOLLIN;
 54     event.data.fd = fd;
 55     epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event);
 56 
 57     struct epoll_event revents[102400];
 58     int iOnline = 0;
 59     while (1)
 60     {
 61         int num = epoll_wait(epfd, revents, 102400, 60 * 1000);
 62         printf("epoll_wait return %d
", num);
 63         if (num > 0)
 64         {
 65             for (int i = 0; i < num; i++)
 66             {
 67                 if (revents[i].data.fd == fd)
 68                 {
 69                     int client;
 70                     struct sockaddr_in cli_addr;
 71                     socklen_t cli_addr_len = sizeof(cli_addr);
 72                     client = accept(fd, (struct sockaddr*)&cli_addr, &cli_addr_len);
 73                     if (client == -1)
 74                     {
 75                         printf("accept failed, error:%s
", strerror(errno));
 76                         if (errno == EMFILE)
 77                         {
 78                             printf("per-process limit reached
");
 79                             exit(errno);
 80                         }
 81                         if (errno == ENFILE)
 82                         {
 83                             printf("system-wide limit reached
");
 84                             exit(errno);
 85                         }
 86                         continue;
 87                     }
 88 
 89                     iOnline++;
 90                     printf("Receive a new connection from %s:%d
", inet_ntoa(cli_addr.sin_addr), cli_addr.sin_port);
 91                     event.events = EPOLLIN;
 92                     event.data.fd = client;
 93                     epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event);
 94                 }
 95             }
 96         }
 97         printf("Online number:%d
", iOnline);
 98     }
 99 
100     return 0;
101 }

client:

 1 package main
 2 
 3 import (
 4     "net"
 5     "fmt"
 6     "time"
 7     "strconv"
 8     "runtime"
 9 )
10 
11 func Connect(host string, port int) {
12     _, err := net.Dial("tcp", host+":"+strconv.Itoa(port))
13     if err != nil {
14         fmt.Printf("Dial to %s:%d failed
", host, port)
15         return
16     }
17 
18     for {
19         time.Sleep(30 * 1000 * time.Millisecond)
20     }
21 }
22 
23 func main() {
24     count := 0
25     for {
26         go Connect("192.168.63.128", 8080)
27         count++;
28         fmt.Printf("Gorutue num:%d
", runtime.NumGoroutine())
29         time.Sleep(100 * time.Millisecond)
30     }
31 }

注:博客园的代码编辑器居然还没有支持go,现在go用的人挺多的啦,希望快点支持啊。

二、开始测试

第一次:

先说结果,连接数达到1031时accept失败了,当时还没有对errno做判断,所以只打印输出了accept失败。

测试Linux下tcp最大连接数限制第1张

然后首先想到的是ulimit -n的限制,查看了一下,默认值1024,然后就是修改这个值,在/etc/security/limits.conf中添加一下内容:

1 *    soft    nofile 102400
2 *    hard    nofile 102400

然后关闭当前xshell连接,重新连接即生效,现在看ulimit -n就是102400了。

这两行的意思就是将每个进程能打开的文件描述符个数的soft、hard限制调整为102400,

注:ulimit -n 102400也可以生效,但是这个修改是临时的。

然后进行第二次测试。

第二次:

逗比了,其实连接数只有2000+,我之前还在奇怪为啥Windows的默认连接数能有这么高呢,原来有些连接已经断了,但是因为我没有做处理,所以以为还在呢,看来我得再安装一个虚拟机了[二哈]

待继续。。。

安装虚拟机去,

时间:2017-12-31 00:09:00

虚拟机安装好了,接着搞,

这次是真的超过10K了。

测试Linux下tcp最大连接数限制第3张测试Linux下tcp最大连接数限制第4张

连接数还在增加,不知道能不能最终达到10万呢,小小的期待ing

时间:2017-12-31 00:41:00,最终上限卡在28232,golang一直报dial失败,由于忘了打印出具体错误信息了,所以无从知道为什么dial失败,所以只能再跑一次T_T

测试Linux下tcp最大连接数限制第5张

 时间:2017-12-31 01:01:00,添加打印dial失败的错误信息的,又跑了一遍,还是在28232时出现dial失败,错误信息:

测试Linux下tcp最大连接数限制第6张

golang的标准库文档中么有对错误信息的解释,从错误信息来看,是分配地址失败,于是想是不是端口地址范围限制了。

测试Linux下tcp最大连接数限制第7张

 查看了一下端口地址范围,确认就是这个限制,由于端口地址是16位,所以,就算把这个端口地址范围修改为1024--65535,也最多能开启64521个连接,而我现在只有一台虚拟机作为客户端,所以想要实现10万连接是不可能了,但是通过这次测试,也让我搞明白了,到底哪些参数会限制连接的上限,这就是我想要的。

最后,感谢Linux内核团队的大神们推出了epoll这么牛逼的机制,才使得我们现在想实现高并发是如此的容易,希望自己有一天也能这么牛逼,哈哈。

元旦假期就这么过了,挺happy的,解决问题之后的这种快感可能就是我们做技术的之所以对技术这么入迷的原因吧。

明天要出去happy了,希望新的一年,自己和家人都好好的。

免责声明:文章转载自《测试Linux下tcp最大连接数限制》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇javax.imageio.IIOException: Can't create output stream! (生成验证码Servlet)MultipartFile(文件的上传)--CommonsMultipartResolver下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

【嵌入式开发】 嵌入式开发工具简介 (裸板调试示例 | 交叉工具链 | Makefile | 链接器脚本 | eclipse JLink 调试环境)

作者 : 韩曙亮 博客地址 : http://blog.csdn.net/shulianghan/article/details/42239705  参考博客 : 【嵌入式开发】嵌入式 开发环境 (远程登录 | 文件共享 | NFS TFTP 服务器 | 串口连接 | Win8.1 + RedHat Enterprise 6.3 + Vmware11)...

Linux下Apache配置HTTPS功能

Apache配置HTTPS功能转https://www.cnblogs.com/liaojiafa/p/6028816.html 一、yum 安装openssl和openssl-devel,httpd-devel 二、生成证书(也可以从公司的证书颁发机构获取): #建立服务器密钥 openssl genrsa -des3 1024 > /...

操作系统复习知识

一、进程和线程 进程和线程的区别: 进程是一个正在执行中的程序,包括程序计数器、寄存器和变量的当前值;一个进程包含一个或多个线程。 进程是操作系统分配资源的最小单位;而线程是作为独立运行和CPU调度的基本单位。 进程间的资源是独立的,而同一进程的各线程间资源是共享的;进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间、建立数据表来维护...

MySQL调优基础, 与hikari数据库连接池配合

1.根据硬件配置系统参数 wait_timeout   非交互连接的最大存活时间, 10-30min    max_connections   全局最大连接数 默认100 根据情况调整    back_log    达到max_connections后, 还能继续接受的连接请求数, linux不超过1000, 根据情况调整  thread_concurre...

解决XP在网络中最大共享连接数的问题

解决XP在网络中最大共享连接数的问题 XP默认并发数是10,若考虑用XP做文件服务器,只能修改TCP/IP并发数方案一:解决方案找一个更改连接数量的软件XP_SP2_TCPIP_Patch.exe下载:http://www.stu-shop.com/upload/XP_SP2_TCPIP_Patch.exe该补丁可把最大连接数修改为255,满足一般...

linux日志守护进程 syslog

  https://www.cnblogs.com/linuxws/p/9017404.html   几乎所有的网络设备都可以通过syslog协议,将日志信息以UDP的形式传送给远端服务器,远端接收日志服务器必须通过syslogd监听UDP端口514,并根据 syslog.conf 配置文件张的配置处理。配置文件 /etc/rsyslog.conf 中...