温馨提示:本文翻译自stackoverflow.com,查看原文请点击:其他 - C/C++: socket() creation fails in the loop, too many open files
c c++ select sockets

其他 - C / C ++:套接字()创建失败,循环中打开文件过多

发布于 2020-04-07 11:44:29

我正在实现一个客户端服务器TCP套接字应用程序。Client在OpenWRT Linux路由器(基于C)上,并以一定的频率反复地将一些数据写在套接字上并成环。Server位于Linux Ubuntu计算机(基于C / C ++)上,并根据数据到达速度循环读取数据。

问题:运行Serverand之后Client,服务器将继续读取新数据。双方合作很好,直到数据交付的数量(连接#)达到1013之后,Client停留在socket(AF_INET,SOCK_STREAM,0)socket creation failed...: Too many open files显然,客户开放fd方法的数量ulimit -n = 1024

我把代码片段显示为Server.cpp的循环结构Client.c

Server.c:

//    TCP Socket creation stuff over here (work as they should):
//    int sock_ = socket() / bind() / listen()

while (1)
{
        socklen_t sizeOfserv_addr = sizeof(serv_addr_);
        fd_set set;
        struct timeval timeout;
        int connfd_;
        FD_ZERO(&set);
        FD_SET(sock_, &set);
        timeout.tv_sec = 10;
        timeout.tv_usec = 0;
        int rv_ = select(sock_ + 1, &set, NULL, NULL, &timeout);
        if(rv_ == -1){
            perror("select");
            return 1;
        }
        else if(rv_ == 0){
            printf("Client disconnected.."); /* a timeout occured */
            close (connfd_);
            close (sock_);
        }
        else{
            connfd_ = accept (sock_,(struct sockaddr*)&serv_addr_,(socklen_t*)&sizeOfserv_addr);
            if (connfd_ >= 0) {
                int ret = read (connfd_, &payload, sizeof(payload));    /* some payload */
                if (ret > 0)
                     printf("Received %d bytes !\n", ret);
                close (connfd_);  /* Keep parent socket open (sock_) */
            }else{
                printf("Server acccept failed..\n");
                close (connfd_);
                close (stcp.sock_);
                return 0;
            }
        }
}

Client.cpp:

while (payload_exist)               /* assuming payload_exist is true */
{
        struct sockaddr_in servaddr;
        int sock;
        if (sock = socket(AF_INET, SOCK_STREAM, 0) == -1)
            perror("socket creation failed...\n");

        int one = 1;
        int idletime = 2;
        setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one));
        setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &idletime, sizeof(idletime));
        setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));

        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = inet_addr("192.168.100.12");
        servaddr.sin_port = htons(PORT);  /* some PORT */
        if (connect (sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) != 0){
            perror("connect failed...");
            return 1;
        }
        write(sock, (struct sockaddr*)&payload, sizeof(payload));  /* some new payload */
        shutdown(sock,SHUT_WR);

        bool serverOff = false;
        while (!serverOff){
             if(read(sock, &res, sizeof(res)) < 0){
                 serverOff = true;
                 close(sock); 
             }
        }
}

注意payload是,800 bytes并且始终会在一write动作中完全传输在定义了这两个代码之后int main(),客户端将继续创建套接字并发送数据,而另一方面close(),由于使用,服务器将接收所有信息并自动接收并在客户端终止时退出select()Client但是,如果我没有通过检查一些打印日志来终止,则很明显Server在客户端崩溃之前成功接收了1013个有效负载socket creation failed...: Too many open files

更新

遵循Steffen Ullrich提到的观点,事实证明,客户端套接字fd没有泄漏,并且fd原始循环(保持打开状态)中存在第二秒ulimit超出了限制。

查看更多

提问者
zlg
被浏览
81
Steffen Ullrich 2020-02-01 03:06
        if(read(sock, &res, sizeof(res)) < 0){
             serverOff = true;
             close(sock);   /********* Not actually closing sock *********/
        }

您的连接终止检查不正确。 read如果另一方已关闭连接且<0仅在发生错误时返回0

    if (sock = socket(AF_INET, SOCK_STREAM, 0) == -1)
        perror("socket creation failed...\n");

鉴于C 中运算符优先级,这基本上表示:

    sock = ( socket(AF_INET, SOCK_STREAM, 0) == -1) )
    if (sock) ...

假设socket(...)不会返回错误而是返回一个文件描述符(即>=0),则比较将为false,因此,sock = 0如果返回的fd为socketwas,这实际上在泄漏文件描述符时表示>0