C ++ select прекращает принимать соединения - PullRequest
1 голос
/ 21 мая 2011


Я пытаюсь сделать select-сервер для получения соединения от нескольких клиентов (все клиенты будут подключаться к одному и тому же порту).
Сервер принимает первых 2 клиентов, но если один из них не отключится, он не примет нового. Я начинаю слушать порт сервера так:

listen(m_socketId, SOMAXCONN);  

и используя команду выбора следующим образом:

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;
}

Надеюсь, этого достаточно :) что с ним не так?

Ответы [ 2 ]

3 голосов
/ 21 мая 2011

Наиболее распространенная ошибка с select() - не повторная инициализация наборов fd на каждой итерации. Второй, третий и четвертый аргументы обновляются при вызове, поэтому вы должны заполнять их снова каждый раз .

Опубликуйте больше кода, чтобы люди действительно могли вам помочь.

Редактировать 0:

fd_set в Windows беспорядок:)

0 голосов
/ 22 мая 2011

Не допускается копировать конструктивные объекты fd_set:

 m_socketReadSet = m_socketMasterSet;

Это в сочетании с правильным утверждением Николая о том, что select изменяет переданный набор, вероятно, объясняет вашу ошибку.

poll (В Windows WSAPoll ) гораздо более удобный API.

Windows также предоставляет WSAEventSelect и (Msg)WaitForMultipleObjects(Ex), которые не имеют прямого эквивалента в Unix, но позволяют одновременно ожидать сокеты, файлы, события синхронизации потоков, таймеры и сообщения пользовательского интерфейса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...