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

现在做服务器开发不加上高并发根本没脸出门,所以为了以后吹水被别人怼“天天提高并发,你自己实现的最高并发是多少”的时候能义正言辞的怼回去,趁着元旦在家没事决定自己写个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\n", 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\n", strerror(errno));
 41         return errno;
 42     }
 43
 44     if (listen(fd, 5) == -1)
 45     {
 46         printf("listen failed, error:%s\n", strerror(errno));
 47         return errno;
 48     }
 49     printf("Listening on 8080...\n");
 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\n", 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\n", strerror(errno));
 76                         if (errno == EMFILE)
 77                         {
 78                             printf("per-process limit reached\n");
 79                             exit(errno);
 80                         }
 81                         if (errno == ENFILE)
 82                         {
 83                             printf("system-wide limit reached\n");
 84                             exit(errno);
 85                         }
 86                         continue;
 87                     }
 88
 89                     iOnline++;
 90                     printf("Receive a new connection from %s:%d\n", 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\n", 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\n", 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\n", runtime.NumGoroutine())
29         time.Sleep(100 * time.Millisecond)
30     }
31 }

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

二、开始测试

第一次:

先说结果,连接数达到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的默认连接数能有这么高呢,原来有些连接已经断了,但是因为我没有做处理,所以以为还在呢,看来我得再安装一个虚拟机了

待继续。。。

安装虚拟机去

原文地址:https://www.cnblogs.com/lit10050528/p/8148723.html

时间: 2024-08-02 17:27:12

测试Linux下tcp最大连接数限制的相关文章

Linux下TCP最大连接数受限问题

一. 文件数限制修改1.用户级别查看Linux系统用户最大打开文件限制:# ulimit -n1024 (1) vi /etc/security/limits.confmysql soft nofile 10240mysql hard nofile 10240其中mysql指定了要修改哪个用户的打开文件数限制.可用'*'号表示修改所有用户的限制:soft或hard指定要修改软限制还是硬限制:10240则指定了想要修改的新的限制值,即最大打开文件数(请注意软限制值要小于或等于硬限制). (2) v

Linux下TCP网络编程与基于Windows下C#socket编程间通信

一.linux下TCP网络编程基础,需要了解相关函数 Socket():用于套接字初始化. Bind():将 socket 与本机上的一个端口绑定,就可以在该端口监听服务请求. Listen():使socket处于被动的监听模式,并为该  socket  建立一个输入数据队列,将到达的服务器, 请求保存在此队列中,直到程序处理他们. Accept():让服务器接收客户的连接请求. Connect():客户端使用connect函数来配置 socket并与远端服务器建立一个 TCP 连接. Clos

Linux下TCP网络编程与基于Windows下C#socket编程之间通信

一.linux下TCP网络编程基础,需要了解相关函数 Socket():用于套接字初始化. Bind():将 socket 与本机上的一个端口绑定,就可以在该端口监听服务请求. Listen():使socket处于被动的监听模式,并为该  socket  建立一个输入 数据队列,将到达的服务器, 请求保存在此队列中,直到程序处理他们. Accept():让服务器接收客户的连接请求. Connect():客户端使用connect函数来配置 socket并与远端服务器建立一个 TCP 连接. Clo

Linux下TCP延迟确认(Delayed Ack)机制导致的时延问题分析

版权声明:本文由潘安群原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/105 来源:腾云阁 https://www.qcloud.com/community 案例一:同事随手写个压力测试程序,其实现逻辑为:每秒钟先连续发N个132字节的包,然后连续收N个由后台服务回显回来的132字节包.其代码简化如下: char sndBuf[132]; char rcvBuf[132]; while (1) { for (int i

Linux下TCP延迟重庆时 时 彩源码下载确认(Delayed Ack)机制导致的时延问题分析

重庆时 时 彩下载联系方式:QQ:2747044651 网址在实际测试中发现,当N大于等于3的情况,第2秒之后,每次第三个recv调用,总会阻塞40毫秒左右,但在分析Server端日志时,发现所有请求在Server端处理时耗均在2ms以下. 当时的具体定位过程如下:先试图用strace跟踪客户端进程,但奇怪的是:一旦strace attach上进程,所有收发又都正常,不会有阻塞现象,一旦退出strace,问题重现.经同事提醒,很可能是strace改变了程序或系统的某些东西(这个问题现在也还没搞清

Linux下TCP的Keepalive相关参数

一 基本原理TCP的Keepalive可以简单理解成为keep tcp alive,用来检测TCP sockets的连接是否正常或是已经断开.Keeplived的原理很简单,当建立一个TCP连接时,发送端就会创建一些计时器,其中一些计时器就是处理keeplaive相关问题的.当keepalive的计时器计数到0时,发送端就会向对端发送一些不含数据的keepalive数据包并开启ACK标志.如果得到keepalive探测包的回复,就可以认为当前的TCP连接正常,不用担心用户层面的具体实现.事实上,

对Linux下TCP连接相关配置的优化记录(转载)

1.Linux系统设置优化,vi /etc/sysctl.conf,添加以下内容 Sysctl.conf代码   fs.file-max = 65535 kernel.pid_max = 65536 net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_synack_retries = 2 net.ipv4.tcp_syn_retries = 2 net.ipv4.tcp_timestsmps = 0 net.ipv4.tcp_tw_reuse = 1 net.ipv

Linux下tcp协议socket的recv函数返回时机分析(粘包)

http://www.vckbase.com/index.php/wv/10http://blog.csdn.net/zlzlei/article/details/7689409 文章一: 当前在网络传输应用中,广泛采用的是TCP/IP通信协议及其标准的socket应用开发编程接口(API).TCP/IP传输层有两个并列的协议:TCP和UDP.其中TCP(transport control protocol,传输控制协议)是面向连接的,提供高可靠性服务.UDP(user datagram pro

Linux下TCP/IP协议栈的简单脉络分析

最近在写网络编程方面的一些东西,然后遇到了关于传输上的小问题.由于之前有简单的看过一些TCP/IP详解的一些东西,所以索性就找了本<追踪LinuxTCP/IP代码运行>的书看了一上午,结果发现初次接触这些内核方面的东西,收获甚微.于是又在网上找相关类的大神博客,拿来拜读,虽然依然看的不是太明白,吸收的也不够好,但是我想以博客的形式把它记录下来,也希望能为我以后学这些东西开个好头吧 1.linux的网络协议栈的主要结构 (1)socket层 这层主要处理socket相关的东西,例如其各种结构的初