मैं क्लाइंट-सर्वर टीसीपी सॉकेट एप्लिकेशन को कार्यान्वित कर रहा हूं। Client एक OpenWRT Linux राउटर (C आधारित) पर है और सॉकेट पर कुछ डेटा बार-बार और कुछ आवृत्ति दर पर लूप में लिखता है। Server एक Linux Ubuntu मशीन (C/C++ आधारित) पर है और डेटा आगमन गति के अनुसार डेटा को लूप में पढ़ता है।

समस्या: Server और फिर Client को चलाने से सर्वर नया डेटा पढ़ता रहता है। डेटा वितरण (# कनेक्शन) की संख्या 1013 तक पहुंचने तक दोनों पक्ष अच्छी तरह से काम करते हैं। उसके बाद, Client socket creation failed...: Too many open files के साथ socket(AF_INET,SOCK_STREAM,0) पर अटक गया। जाहिर है, क्लाइंट पर खुले fd की संख्या ulimit -n = 1024 के करीब पहुंचती है।

मैं कोड के स्निपेट डालता हूं जो Server.cpp और Client.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;
            }
        }
}

क्लाइंट.सीपीपी:

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 को समाप्त नहीं करता, हालांकि, कुछ प्रिंट लॉग की जांच करके, यह स्पष्ट है कि socket creation failed...: Too many open files के साथ क्लाइंट क्रैश होने से पहले Server सफलतापूर्वक १०१३ पेलोड प्राप्त करता है।

अपडेट करें:

स्टीफन उलरिच द्वारा बताए गए बिंदु के बाद, यह पता चला कि, क्लाइंट सॉकेट fd में कोई रिसाव नहीं है, और मूल लूप (जो खुला छोड़ दिया गया था) में एक सेकंड fd का अस्तित्व बना रहा था ulimit सीमा से अधिक है।

0
zlg 31 जिंदा 2020, 21:24

1 उत्तर

सबसे बढ़िया उत्तर
        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) तुलना झूठी होगी और इस प्रकार यह अनिवार्य रूप से कहता है sock = 0 फ़ाइल डिस्क्रिप्टर को लीक करते समय यदि fd द्वारा लौटाया जाता है socket, >0 था।

4
Steffen Ullrich 31 जिंदा 2020, 22:06