TCP服务器不能接受超过1000的客户端连接?

书瑶

遇到一个奇怪的问题,当我手动运行一个TCP程序(./tcpServDemo)时,tcp Server程序可以接收超过5000个客户端连接,但是当我在后台运行tcpServerDemo时(systemctl start tcpServDemo.service),却只能接收超过 900 个客户端连接,

当我调试时,我发现 TCP recv-Q 队列已满。我修改了TCP参数(net.core.somaxconn = 65500 net.ipv4.tcp_max_syn_backlog = 409600),但是还是不行

我已经调试了几天。真不知道问题出在哪里?谁能帮帮我,谢谢大家!

操作系统:CentOS 7.9

tcpClient.c:
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <netinet/in.h>
#include <pthread.h>

//#define SERVPORT 8088
 
int ServPort;
char ServerIP[32];

pthread_mutex_t lock;
int count;

void *cTcpConn(void *arg) {
    usleep(2000);
    int sockfd,sendbytes;
    struct sockaddr_in serv_addr;//需要连接的服务器地址信息
    memset(&serv_addr, 0, sizeof(struct sockaddr_in));

    //1.创建socket
    //AF_INET 表示IPV4
    //SOCK_STREAM 表示TCP
    if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) {
        printf("socket create failed.");
        return NULL;
    }


    //填充服务器地址信息
    serv_addr.sin_family    = AF_INET; //网络层的IP协议: IPV4
    serv_addr.sin_port      = htons(ServPort); //传输层的端口号
    serv_addr.sin_addr.s_addr   = inet_addr(ServerIP); //网络层的IP地址: 实际的服务器IP地址

    //2.发起对服务器的连接信息
    //三次握手,需要将sockaddr_in类型的数据结构强制转换为sockaddr
    if((connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(struct sockaddr))) < 0) {
        printf("connect failed!\n");
        close(sockfd);
        return NULL;
    } else {
        pthread_mutex_lock(&lock);
        count++;
        pthread_mutex_unlock(&lock);
        printf("connect successful! count:%d\n", count);
    }


#if 0
    //3.发送消息给服务器端
    if((sendbytes = send(sockfd,"hello",5,0)) < 0) {
        perror("send");
        exit(1);
    }
#endif

    while(1) {
        sleep(10);
    }

    //4.关闭
    close(sockfd);

    return NULL;
}

int main(int argc, char **argv) {
    if (argc != 3) {
        printf("Usage: %s ServerIP ServerPort\n", argv[0]);
        return 0;
    }

    strncpy(ServerIP, argv[1], sizeof(ServerIP) - 1);
    ServPort = atoi(argv[2]);
    

    int i;
    pthread_t pid;

    for (i = 0; i < 8000; i++) {
        usleep(10000);
        if(0 != pthread_create(&pid, NULL, cTcpConn, NULL)) {
            printf("thread create failed.\n");
        }
    }

    while (1) {
        sleep(10);
    }
    return 0;
}

tcpServDemo.c:

#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>


int main() {
    const int EVENTS_SIZE = 4096;
    char buff[1024];
    int eNum;

    int socketFd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    struct sockaddr_in sockAddr;
    sockAddr.sin_port = htons(8088);
    sockAddr.sin_family = AF_INET;
    sockAddr.sin_addr.s_addr = htons(INADDR_ANY);

    if (bind(socketFd, (struct sockaddr *) &sockAddr, sizeof(sockAddr)) == -1) {
        return -1;
    }

    if (listen(socketFd, 10) == -1) {
        return -1;
    }

    int eFd = epoll_create(1);

    struct epoll_event epev;
    epev.events = EPOLLIN;
    epev.data.fd = socketFd;
    epoll_ctl(eFd, EPOLL_CTL_ADD, socketFd, &epev);
    
    int i;
    int count = 0;
    struct epoll_event events[EVENTS_SIZE];

    while (1) {
        eNum = epoll_wait(eFd, events, EVENTS_SIZE, -1);

        if (eNum == -1) {
            return -1;
        }
        for (i = 0; i < eNum; i++) {
            if (events[i].data.fd == socketFd) {
                if (events[i].events & EPOLLIN) {
                    struct sockaddr_in cli_addr;
                    socklen_t length = sizeof(cli_addr);
                    int fd = accept(socketFd, (struct sockaddr *) &cli_addr, &length);
                    if (fd > 0) {
                        count++;
                        epev.events = EPOLLIN | EPOLLET;
                        epev.data.fd = fd;

                        int flags = fcntl(fd, F_GETFL, 0);
                        if (flags < 0) {
                            continue;
                        }
                        if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
                            continue;
                        }

                        epoll_ctl(eFd, EPOLL_CTL_ADD, fd, &epev);
                        printf("client on line fd:%d-count:%d\n", fd, count);
                    }  else {
                        printf("accept failed.\n, fd:%d-errno:%d-strerror:%s\n", fd, errno, strerror(errno));
                    }
                }
            } else {
                if (events[i].events & EPOLLERR || events[i].events & EPOLLHUP) {
                    epoll_ctl(eFd, EPOLL_CTL_DEL, events[i].data.fd, NULL);
                    close(events[i].data.fd);
                }
            }
        }
    }
}

/usr/lib/systemd/system/tcpServDemo.service:

[Unit]
Description= application service monitor daemon
After=network.target                                                                                                                                         

[Service]
User=root
Type=forking
ExecStart=/var/workstation/testcode/C-Code/tcpServDemo
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=1s

[Install]
WantedBy=multi-user.target graphic.target


艾伦温德

你的文件描述符用完了。accept()会返回-1并设置errno为 EMFILE。与我们分享该错误消息会很有帮助。您可以通过以下方式提高(软)文件描述符限制

  1. LimitNOFILESoft您的服务文件设置为合适的更高值(请参阅 参考资料systemd.exec(5)),或
  2. 以低于的价格调用setrlimit(RLIMIT_NOFILE, ...)更高的值服务器将其设置为检索自是很正常的,因此您可以在外部调整资源使用情况(在这种情况下为文件描述符的数量)。rlim_currlimit_maxrlimit_currlimit_maxgetrlimit(RLIMIT_NOFILE, ...)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

服务器套接字不能接受客户端。(C# UWP 异步套接字编程)

TCP客户端不能统一随机连接到本地服务器

TCP 客户端 - 服务器连接

在TCP连接中,服务器怎么可能同时处理超过65535个客户端?

TCP 服务器不接受客户端发出的正确数量的连接,并且侦听积压较少

C ++套接字服务器不接受任何客户端/客户端将无法连接

如何接受一个TCP服务器的多个客户端?

树莓派上的TCP服务器未连接到树莓派上的android tcp客户端

我的TCP客户端未连接到我的TCP服务器

TCP客户端无法连接到TCP服务器

TCP客户端连接到两个TCP服务器

TCP让服务器先关闭连接让客户端先关闭连接

服务器不接受来自客户端的连接以从文件读取数据

服务器中的accept()函数似乎不接受来自客户端的新连接

使用C#的TCP / IP服务器/客户端多连接并接收客户端的公共IP地址

让TCP客户端搜索TCP服务器

Java服务器-多客户端TCP连接I / O

从客户端C#连接到多个TCP服务器

服务器关闭后,TCP / IP客户端重新连接

TCP客户端程序无法连接到我的服务器

TCP连接以及客户端和服务器的不同缓冲区大小

客户端即使积压队列已满也连接到TCP迭代服务器

检查Java TCP服务器上的客户端断开连接-仅输出

是否可以在Winsock中将TCP服务器连接到udp客户端

从Java游戏服务器到客户端的TCP和UDP连接

我应该为基于tcp的服务器-客户端连接使用相同的端口吗

TCP服务器localhost客户端随机断开连接

最小的 TCP 客户端-服务器:accept() 从不接收连接?

Boost ASIO Tcp客户端/服务器对象连接问题