当前位置:首页 > 操作系统 > Linux

测试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 16int SetReuseAddr(int fd)
 17{
 18int optval = 1;
 19     socklen_t optlen = sizeof(optval);
 20return setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, optlen);
 21}
 22 23int main()
 24{
 25int fd = socket(AF_INET, SOCK_STREAM, 0);
 26int iRet = SetReuseAddr(fd);
 27if (iRet != 0)
 28    {
 29         printf("setsockopt for SO_REUSEADDR failed, error:%sn", strerror(iRet));
 30return iRet;
 31    }
 32 33struct 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;
 38if (bind(fd, (struct sockaddr*)&addr, sizeof(addr))  == -1)
 39    {
 40         printf("bind failed, error:%sn", strerror(errno));
 41return errno;
 42    }
 43 44if (listen(fd, 5) == -1)
 45    {
 46         printf("listen failed, error:%sn", strerror(errno));
 47return errno;
 48    }
 49     printf("Listening on 8080...n");
 50 51int epfd = epoll_create(102400);
 52struct epoll_event event;
 53event.events = EPOLLIN;
 54event.data.fd = fd;
 55     epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event);
 56 57struct epoll_event revents[102400];
 58int iOnline = 0;
 59while (1)
 60    {
 61int num = epoll_wait(epfd, revents, 102400, 60 * 1000);
 62         printf("epoll_wait return %dn", num);
 63if (num > 0)
 64        {
 65for (int i = 0; i < num; i++)
 66            {
 67if (revents[i].data.fd == fd)
 68                {
 69int client;
 70struct sockaddr_in cli_addr;
 71                     socklen_t cli_addr_len = sizeof(cli_addr);
 72                     client = accept(fd, (struct sockaddr*)&cli_addr, &cli_addr_len);
 73if (client == -1)
 74                    {
 75                         printf("accept failed, error:%sn", strerror(errno));
 76if (errno == EMFILE)
 77                        {
 78                             printf("per-process limit reachedn");
 79                            exit(errno);
 80                        }
 81if (errno == ENFILE)
 82                        {
 83                             printf("system-wide limit reachedn");
 84                            exit(errno);
 85                        }
 86continue;
 87                    }
 88 89                     iOnline++;
 90                     printf("Receive a new connection from %s:%dn", inet_ntoa(cli_addr.sin_addr), cli_addr.sin_port);
 91event.events = EPOLLIN;
 92event.data.fd = client;
 93                     epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event);
 94                }
 95            }
 96        }
 97         printf("Online number:%dn", iOnline);
 98    }
 99100return0;
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))
13if err != nil {
14         fmt.Printf("Dial to %s:%d failedn", host, port)
15return16    }
1718for {
19         time.Sleep(30 * 1000 * time.Millisecond)
20    }
21}
2223func main() {
24     count := 025for {
26         go Connect("192.168.63.128", 8080)
27         count++;
28         fmt.Printf("Gorutue num:%dn", 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 1024002 *    hard    nofile 102400

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

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

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

然后进行第二次测试。

第二次:

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

待继续。。。

安装虚拟机去

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


【说明】本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:254677821)!

相关教程推荐

其他课程推荐