Как получить данные в основном цикле клиента C ++, не закрывая сокет сервера? - PullRequest
1 голос
/ 28 февраля 2012

Я читал этот пример winsock .

Я пытаюсь осмыслить, как создать клиентскую программу C ++, которая имеет постоянное соединение TCP / IP с сервером C # .NET.

Проблема, которую я вижу, состоит в том, что для того, чтобы клиент C ++ мог выйти из цикла приема, сервер должен закрыть свое сокетное соединение с клиентом.

В моем случае сервер будет отправлять клиенту каждые пару секунд. Мне нужно иметь возможность получить один пакет с сервера и перезапустить основной цикл программы, чтобы клиент мог выполнить все остальные функции.

Если этот код приема находится в основном цикле клиента C ++, клиент никогда не прекратит прием, если сервер никогда не закроет соединение с клиентом:

// Receive until the peer closes the connection

do {

    iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
    if ( iResult > 0 )
        printf("Bytes received: %d\n", iResult);
    else if ( iResult == 0 )
        printf("Connection closed\n");
    else
        printf("recv failed with error: %d\n", WSAGetLastError());

} while( iResult > 0 );

Ответы [ 2 ]

2 голосов
/ 28 февраля 2012

Пример программы, из которой вы выбрали работу, предназначен для отправки одного запроса и получения одного ответа. Он использует состояние соединения для указания конца запроса и конца ответа.

Возможно, вы захотите работать с другой программой-примером. Поищите в Google пример "winsock chat".

С другой стороны, чтобы изменить эту программу, как вы просили, вы можете заменить цикл do-while следующим:

// Assume that the OP's protocol sends 100-byte packets. 
// Each while iteration attempts to receive one such packet.
// The while exits when the other side closes its connection.
while(1) {
    // Receive 100-byte packet 
    int receivedBytes;
    for(receivedBytes = 0; receivedBytes < 100; ) {
        int iResult = recv(ConnectSocket,
                           recvbuf+receivedBytes,
                           recvbuflen-receivedBytes, 0);

        if ( iResult > 0 ) {
            receivedBytes += iResult;
            printf("Bytes received: %d\n", iResult);
        } else if ( iResult == 0 ) {
            printf("Connection closed\n");
            break;
        } else {
            printf("recv failed with error: %d\n", WSAGetLastError());
            break;
        }
    }
    if(receivedBytes == 100) {
        // ... process packet here
    } else {
        break;
    }
}
1 голос
/ 28 февраля 2012

Проблема в том, что у вас нет возможности узнать, в какой момент функция recv () вернется.Есть пять обходных путей:

  1. Сделать сокет неблокирующим.(Не рекомендуется)
  2. Использовать select () с таймаутом.
  3. Использовать асинхронные сокеты.Это, вероятно, самый быстрый способ, но более сложный.
  4. Использовать поток.
  5. BSD kqueue
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...