繁体   English   中英

accept为第二,第三等客户端返回0

[英]accept returns 0 for 2nd, 3rd, etc client

我正在写一个简单的套接字服务器/客户端应用程序。 我遇到一个有趣的问题。 在我的服务器代码中,我像这样在非阻塞套接字上调用accept

while ((res = accept(m_sd, NULL, 0)) >= 0) { // There are new clients
  ... // Saving res as fd etc
}

一切工作正常-当有客户端时,accept将返回有效的文件描述符。 但是,当第一个客户端断开连接而第二个客户端连接时,accept返回0-这是一个有效的FD,但是,此描述符上的所有操作都会失败。 下一个客户端也会发生这种情况-accept返回0。在随机数量的客户端之后,acceptor返回一个“有效”(非零)除数,然后重复。

注意:如果没有客户端,则使用errno EAGAIN接受预期的返回-1-完全可以。 当accept返回零时,未设置errno。

是什么导致这种奇怪的行为?

这是我创建服务器套接字的方法:

     struct sockaddr_in serv_addr;
     m_sd = socket(AF_INET, SOCK_STREAM, 0);
     if (m_sd < 0){}
        //Handle error

     bzero((char *)&serv_addr, sizeof(serv_addr));
     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(port);
     int optval = 1;
     setsockopt(m_sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval);

     if (bind(m_sd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
         // Handle error
     }
     fcntl(m_sd, F_SETFL, O_NDELAY); // Make socket non-blocking

     listen(m_sd, 50);

这是我创建客户端的方法:

    int rc;
    struct sockaddr_in serveraddr;
    struct hostent *hostp;
    m_sd = socket(AF_INET, SOCK_STREAM, 0);
    if (m_sd < 0)
           // Handle error
    memset(&serveraddr, 0, sizeof(struct sockaddr_in));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(port);

    hostp = gethostbyname(hostname.c_str());
    if (hostp == NULL)
      // Handle error

    memcpy(&serveraddr.sin_addr, hostp->h_addr, sizeof(serveraddr.sin_addr));

    // connect to serveraddr
    rc = connect(m_sd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
    if (rc < 0)
      //Handle error
    //set to nonblocking
    fcntl(m_sd, F_SETFL, fcntl(m_sd, F_GETFL, 0) | O_NONBLOCK);

这是代码,在那里我等待来自任何客户端的新数据:

    struct timeval tv;

    tv.tv_sec = 0;
    tv.tv_usec = std::chrono::duration_cast<std::chrono::microseconds>(timeout).count();

    fd_set rfds;
    FD_ZERO(&rfds);
    FD_SET(m_sd, &rfds);
    int end = m_sd;
    for (const auto& s : m_clients) {
        end = std::max(end, s.second.m_sd);
        FD_SET(s.second.m_sd, &rfds);
    }

    int retval = select(end + 1, &rfds, NULL, NULL, &tv);
    if (retval == -1) {
       // Error handling
    }
    return retval > 0; // There is pending data from client

问题解决了! 我不小心在代码中关闭了fd 0,这导致了这种奇怪的行为。 现在一切正常。 感谢您的帮助-您向我展示了正确的方法

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM