繁体   English   中英

C ++ select停止接受连接

[英]C++ select stops accepting connections


我试图做一个选择服务器,以接收来自多个客户端的连接(所有客户端都将连接到同一端口)。
服务器接受前两个客户端,但是除非其中一个断开连接,否则它将不接受新的客户端。 我开始像这样监听服务器端口:

listen(m_socketId, SOMAXCONN);  

并使用如下所示的select命令:

int selected = select(m_maxSocketId + 1, &m_socketReadSet, NULL, NULL, 0);

我添加了一些代码。

bool TcpServer::Start(char* ipAddress, int port)
{
    m_active = true;
    FD_ZERO(&m_socketMasterSet);
    bool listening = m_socket->Listen(ipAddress, port);
    // Start listening.

    m_maxSocketId = m_socket->GetId();
    FD_SET(m_maxSocketId, &m_socketMasterSet);
    if (listening == true)
    {
        StartThread(&InvokeListening);
        StartReceiving();
        return true;
    }
    else
    {
        return false;
    }
}

void TcpServer::Listen()
{
    while (m_active == true)
    {
        m_socketReadSet = m_socketMasterSet;
        int selected = select(m_maxSocketId + 1, &m_socketReadSet, NULL, NULL, 0);
        if (selected <= 0)
            continue;
        bool accepted = Accept();
        if (accepted == false)
        {
            ReceiveFromSockets();
        }
    }
}

bool TcpServer::Accept()
{
    int listenerId = m_socket->GetId();
    if (FD_ISSET(listenerId, &m_socketReadSet) == true)
    {
        struct sockaddr_in remoteAddr;
        int addrSize = sizeof(remoteAddr);
        unsigned int newSockId = accept(listenerId, (struct sockaddr *)&remoteAddr, &addrSize);
        if (newSockId == -1) // Invalid socket...
        {
            return false;
        }
        if (newSockId > m_maxSocketId)
        {
            m_maxSocketId = newSockId;
        }

        m_clientUniqueId++;
        // Remembering the new socket, so we'll be able to check its state
        // the next time.
        FD_SET(newSockId, &m_socketMasterSet);

        CommEndPoint remote(remoteAddr);
        CommEndPoint local = m_socket->GetLocalPoint();

        ClientId* client = new ClientId(m_clientUniqueId, newSockId, local, remote);
        m_clients.Add(client);
        StoreNewlyAcceptedClient(client);
        char acceptedMsg = CommInternalServerMsg::ConnectionAccepted;
        Server::Send(CommMessageType::Internal, client, &acceptedMsg, sizeof(acceptedMsg));
        return true;
    }

    return false;
}

我希望这是足够的:)它怎么了?

到目前为止, select()最常见错误是没有在每次迭代中重新初始化fd集。 调用会更新第二,第三和第四自变量,因此您每次都必须再次填充它们。

发布更多代码,以便人们实际上可以为您提供帮助。

编辑0:

Windows上的fd_set很乱:)

不允许复制构造fd_set对象:

 m_socketReadSet = m_socketMasterSet;

这与尼古拉(Nikolai)的正确select更改更改的设置)相结合,可能是导致您出错的原因。

poll (在Windows上为WSAPoll )是一个更加友好的API。

Windows还提供了WSAEventSelect(Msg)WaitForMultipleObjects(Ex) ,它们在Unix上没有直接等效的功能,但允许您同时等待套接字,文件,线程同步事件,计时器和UI消息。

暂无
暂无

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

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