测试Linux下tcp最大连接数限制
现在做服务器开发不加上高并发根本没脸出门,所以为了以后吹水被别人怼“天天提高并发,你自己实现的最高并发是多少”的时候能义正言辞的怼回去,趁着元旦在家没事决定自己写个demo搞一搞。
这个测试主要是想搞明白Linux下哪些参数配置限制了连接数的最大值,上限是多少。
一、先说下demo的思路:
服务端用epoll实现,就是简简单单的接收连接,然后客户端用go的goroutine,每个goroutine就是简单的建立连接,然后什么也不做。
上代码:
server:g++ -o test_epoll ./test_epoll.c && ./test_epoll
/*
* g++ -o test_epoll ./test_epoll.c
*/
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <arpa/inet.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h> int SetReuseAddr(int fd)
{
int optval = 1;
socklen_t optlen = sizeof(optval);
return setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, optlen);
} int main()
{
int fd = socket(AF_INET, SOCK_STREAM, 0);
int iRet = SetReuseAddr(fd);
if (iRet != 0)
{
printf("setsockopt for SO_REUSEADDR failed, error:%s\n", strerror(iRet));
return iRet;
} struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(8080);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1)
{
printf("bind failed, error:%s\n", strerror(errno));
return errno;
} if (listen(fd, 5) == -1)
{
printf("listen failed, error:%s\n", strerror(errno));
return errno;
}
printf("Listening on 8080...\n"); int epfd = epoll_create(102400);
struct epoll_event event;
event.events = EPOLLIN;
event.data.fd = fd;
epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event); struct epoll_event revents[102400];
int iOnline = 0;
while (1)
{
int num = epoll_wait(epfd, revents, 102400, 60 * 1000);
printf("epoll_wait return %d\n", num);
if (num > 0)
{
for (int i = 0; i < num; i++)
{
if (revents[i].data.fd == fd)
{
int client;
struct sockaddr_in cli_addr;
socklen_t cli_addr_len = sizeof(cli_addr);
client = accept(fd, (struct sockaddr*)&cli_addr, &cli_addr_len);
if (client == -1)
{
printf("accept failed, error:%s\n", strerror(errno));
if (errno == EMFILE)
{
printf("per-process limit reached\n");
exit(errno);
}
if (errno == ENFILE)
{
printf("system-wide limit reached\n");
exit(errno);
}
continue;
} iOnline++;
printf("Receive a new connection from %s:%d\n", inet_ntoa(cli_addr.sin_addr), cli_addr.sin_port);
event.events = EPOLLIN;
event.data.fd = client;
epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event);
}
}
}
printf("Online number:%d\n", iOnline);
} return 0;
}
client:go run client.go
package main import (
"net"
"fmt"
"time"
"strconv"
"runtime"
) func Connect(host string, port int) {
_, err := net.Dial("tcp", host+":"+strconv.Itoa(port))
if err != nil {
fmt.Printf("Dial to %s:%d failed\n", host, port)
return
} for {
time.Sleep(30 * 1000 * time.Millisecond)
}
} func main() {
count := 0
for {
go Connect("192.168.63.128", 8080)
count++;
fmt.Printf("Gorutue num:%d\n", runtime.NumGoroutine())
time.Sleep(100 * time.Millisecond)
}
}
二、开始测试
第一次:
先说结果,连接数达到1031时accept失败了,当时还没有对errno做判断,所以只打印输出了accept失败。
然后首先想到的是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了。
连接数还在增加,不知道能不能最终达到10万呢,小小的期待ing
时间:2017-12-31 00:41:00,最终上限卡在28232,golang一直报dial失败,由于忘了打印出具体错误信息了,所以无从知道为什么dial失败,所以只能再跑一次T_T
时间:2017-12-31 01:01:00,添加打印dial失败的错误信息的,又跑了一遍,还是在28232时出现dial失败,错误信息:
golang的标准库文档中么有对错误信息的解释,从错误信息来看,是分配地址失败,于是想是不是端口地址范围限制了。
查看了一下端口地址范围,确认就是这个限制,由于端口地址是16位,所以,就算把这个端口地址范围修改为1024--65535,也最多能开启64521个连接,而我现在只有一台虚拟机作为客户端,所以想要实现10万连接是不可能了,但是通过这次测试,也让我搞明白了,到底哪些参数会限制连接的上限,这就是我想要的。
最后,感谢Linux内核团队的大神们推出了epoll这么牛逼的机制,才使得我们现在想实现高并发是如此的容易,希望自己有一天也能这么牛逼,哈哈。
测试Linux下tcp最大连接数限制的更多相关文章
- Linux下TCP最大连接数受限问题
一. 文件数限制修改1.用户级别查看Linux系统用户最大打开文件限制:# ulimit -n1024 (1) vi /etc/security/limits.confmysql soft nofil ...
- linux下TCP/IP及内核参数优化调优(转)
Linux下TCP/IP及内核参数优化有多种方式,参数配置得当可以大大提高系统的性能,也可以根据特定场景进行专门的优化,如TIME_WAIT过高,DDOS攻击等等. 如下配置是写在sysctl.con ...
- Linux下TCP网络编程与基于Windows下C#socket编程间通信
一.linux下TCP网络编程基础,需要了解相关函数 Socket():用于套接字初始化. Bind():将 socket 与本机上的一个端口绑定,就可以在该端口监听服务请求. Listen():使s ...
- 20155322 2017-2018-1《信息安全系统设计》第二周 课堂测试 Linux下C语言实现MYOD
20155322 2017-2018-1<信息安全系统设计>第二周 课堂测试 Linux下C语言实现MYOD [博客目录] 静态库测试 实现方法 相关资料 操作 动态库测试 实现方法 相关 ...
- Linux下TCP延迟确认(Delayed Ack)机制导致的时延问题分析
版权声明:本文由潘安群原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/105 来源:腾云阁 https://www.qclo ...
- 测试linux下磁盘的读写速率
1) 通过df -h命令查看磁盘情况 Filesystem Size Used Avail Use% Mounted on/dev/sda4 289G ...
- 提升linux下tcp服务器并发连接数限制
1.修改用户进程可打开文件数限制 在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统 ...
- 提升linux下TCP服务器并发连接数(limit)
https://cloud.tencent.com/developer/article/1069900 1.修改用户进程可打开文件数限制 在Linux平台上,无论编写客户端程序还是服务端程序,在进 ...
- Linux下查看apache连接数
1.查看apache当前并发访问数: netstat -an | grep ESTABLISHED | wc -l 对比httpd.conf中MaxClients的数字差距多少. 2.查看有多少个进程 ...
随机推荐
- mysql命令行使用
连接数据库 mysql -P 端口号 -h 远程机地址/ip -u 用户名 -p mysql -uroot -p123456 修改数据库密码 mysqladmin -uroot -p123456 ...
- selenium 安装
selenium 安装 一.chromerdriver 1.浏览器版本 1)检查谷歌浏览器版本 打开chrome输入 "chrome://version/"查看版本,如图所示: 2 ...
- qsort函数排序各种类型的数据。
qsort函数是库函数中的一员,我们先来看看官方文档是怎么写的: 其中qsort的参数void* base是传入一个数组,size_t num 为数组整体大小,size_t size 为单个元素的大小 ...
- 解决ansible上传速度慢的问题
问题: 假如有A.B.C.D....等机器,机器A为Ansible服务器,机器B.C.D...等为Ansible管理的节点服务器,A机器与其他机器都不在同一个网络,也就是A机器必须添加VPN之后才能与 ...
- 如何将极客时间课程制作成kindle电子书
订阅了几个极客时间的专栏,一直没有时间去看. 最近,想着如果把内容制作成电子书,利用上下班时间学习一下,岂不是很方便? 在网上搜到一个很好用的开源软件,几分钟就可以把极客时间的专栏做成电子书,简直太棒 ...
- 关于各种BUF源语的研究
关于各种BUF源语的研究 资料来源: 单端信号需要用到的BUF 关于这些源语的约束: 增大驱动电流 关于管脚的上拉与下拉约束: ODDR的两种操作模式 关于ODDR输出时钟的应用 为什么ODDR需要这 ...
- 在Win10 Anaconda中安装Tensorflow
有需要的朋友可以参考一下 1.安装Anaconda 下载:https://www.continuum.io/downloads,我用的是Python 3.5 下载完以后,安装. 安装完以后,打开A ...
- android查看屏幕密度,分辨率的shell命令
adb shell dumpsys window displays
- spring mvc 注解整理(一)
@Controller和@RestController: RestController = @ResponseBody + @Controller 所有返回都是json类型,无法跳转到jsp页面,但 ...
- 【亲测】关于HTTP协议~
如果有一点点基本的开发者工具基础知识,我们知道:Elements是用来查看网页结构的,也就是可以看到整体的HTML语言:Console是控制台,Network是请求想相应状态. 1)一个Name就是一 ...