2 micobest micobest 于 2013.10.22 03:07 提问

Linux下epoll并发数量达到1987个后涨不上去

Linux下epoll并发数量达到1987个后涨不上去(达到1987个链接后,无法接受新链接,并非最大开文件句柄限制所导致)

我在linux下写来一个简单的epoll server程序,在局域网中另一台windows计算机采用多线程的形式链接server,但是大概epoll链接了1987个套接字后,再也不能增加新链接了(并非最大文件句柄数量所限制),不清楚所什么原因,跪求解答,谢谢各位好心人。

server代码:

#include
#include /* basic system data types /
#include /
basic socket definitions /
#include /
sockaddr_in{} and other Internet defns /
#include /
inet(3) functions /
#include /
epoll function /
#include /
nonblocking */
#include /*setrlimit */

#include
#include
#include
#include

#define MAXEPOLLSIZE 10000
#define MAXLINE 10240
int handle(int connfd);
int setnonblocking(int sockfd)
{
if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1) {
return -1;
}
return 0;
}

int main(int argc, char **argv)
{
int servPort = 6888;
int listenq = 1024;

int listenfd, connfd, kdpfd, nfds, n, nread, curfds,acceptCount = 0;
struct sockaddr_in servaddr, cliaddr;
socklen_t socklen = sizeof(struct sockaddr_in);
struct epoll_event ev;
struct epoll_event events[MAXEPOLLSIZE];
struct rlimit rt;
char buf[MAXLINE];

/* 设置每个进程允许打开的最大文件数 */
rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE;
if (setrlimit(RLIMIT_NOFILE, &rt) == -1) 
{
    perror("setrlimit error");
    return -1;
}


bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET; 
servaddr.sin_addr.s_addr = htonl (INADDR_ANY);
servaddr.sin_port = htons (servPort);

listenfd = socket(AF_INET, SOCK_STREAM, 0); 
if (listenfd == -1) {
    perror("can't create socket file");
    return -1;
}

int opt = 1;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

if (setnonblocking(listenfd) < 0) {
    perror("setnonblock error");
}

if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) == -1) 
{
    perror("bind error");
    return -1;
} 
if (listen(listenfd, listenq) == -1) 
{
    perror("listen error");
    return -1;
}
/* 创建 epoll 句柄,把监听 socket 加入到 epoll 集合里 */
kdpfd = epoll_create(MAXEPOLLSIZE);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = listenfd;
if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, listenfd, &ev) < 0) 
{
    fprintf(stderr, "epoll set insertion error: fd=%d\n", listenfd);
    return -1;
}
curfds = 1;

printf("epollserver startup,port %d, max connection is %d, backlog is %d\n", servPort, MAXEPOLLSIZE, listenq);

for (;;) {
    /* 等待有事件发生 */
    nfds = epoll_wait(kdpfd, events, curfds, -1);
    if (nfds == -1)
    {
        perror("epoll_wait");
        continue;
    }
    /* 处理所有事件 */
    for (n = 0; n < nfds; ++n)
    {
        if (events[n].data.fd == listenfd) 
        {
            connfd = accept(listenfd, (struct sockaddr *)&cliaddr,&socklen);
            if (connfd < 0) 
            {
                perror("accept error");
                continue;
            }

            sprintf(buf, "accept form %s:%d\n", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port);
            printf("%d:%s", ++acceptCount, buf);

            if (curfds >= MAXEPOLLSIZE) {
                fprintf(stderr, "too many connection, more than %d\n", MAXEPOLLSIZE);
                close(connfd);
                continue;
            } 
            if (setnonblocking(connfd) < 0) {
                perror("setnonblocking error");
            }
            ev.events = EPOLLIN | EPOLLET;
            ev.data.fd = connfd;
            if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, connfd, &ev) < 0)
            {
                fprintf(stderr, "add socket '%d' to epoll failed: %s\n", connfd, strerror(errno));
                return -1;
            }
            curfds++;
    printf("%d\n", curfds);
            continue;
        } 
        // 处理客户端请求
        if (handle(events[n].data.fd) < 0) {
            epoll_ctl(kdpfd, EPOLL_CTL_DEL, events[n].data.fd,&ev);
            curfds--;


        }
    }
}
close(listenfd);
return 0;

}
int handle(int connfd) {
int nread;
char buf[MAXLINE];
nread = read(connfd, buf, MAXLINE);//读取客户端socket流

if (nread == 0) {
    printf("client close the connection\n");
    close(connfd);
    return -1;
} 
if (nread < 0) {
    perror("read error");
    close(connfd);
    return -1;
}    
write(connfd, buf, nread);//响应客户端  
return 0;

}

1个回答

NK_test
NK_test   Rxr 2016.04.23 23:48

确认不是客户端的问题?

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!