Как проверить, отключен ли клиент через Winsock на С++?

Как проверить, отключен ли клиент через Winsock на С++?

Ответ 1

Руководство по программированию сети Beej

если вы вызываете recv в режиме блокировки, и он возвращается с чтением 0 байтов, сокет отключен, иначе он ожидает получения байтов.

Посмотрите FAQ 2.12

Например, выберите эту страницу.

int nRet;

if(( nRet = select( 0, &fdread, NULL, NULL, NULL )) == SOCKET_ERROR )
{
    // Error condition
    // Check WSAGetLastError
}

if( nRet > 0 )
{
    // select() will return value 1 because i m using only one socket
    // At this point, it should be checked whether the
    // socket is part of a set.

    if( FD_ISSET( s, &fdread ))
    {
        // A read event has occurred on socket s
    }
}

Ответ 2

Вы можете узнать, отключен ли сокет TCP, пытаясь отправить данные. Это связано с тем, что дизайн протокола таков, что он предполагает возможность временного отключения между одноранговыми узлами. Итак, если вы подключаетесь из A через R1 через R2 через R3 в B и некоторое время отправляете данные, а затем прекратите отправку, вы можете отключить R2- > R3 (например), и ни A, ни B не заметили (или не обратили внимание). Если вы затем подключили R2- > R4 и R4- > R3, а затем попытались отправить данные между A и B, тогда все будет "работать", и вы никогда не узнаете. Если, однако, вы попытались отправить данные, когда R2- > R3 был отключен, тогда вы (в конце концов, после всех попыток TCP-уровня) получите сообщение об ошибке.

Теперь некоторые операционные системы могут предупредить вас о том, что ваш локальный сетевой адаптер в настоящее время не подключен, и вы можете использовать это, чтобы сказать: "Я больше не подключен к моим сверстникам", но я бы не стал посоветуйте это.

Если ваши сверстники знают, когда соединения "сломаны" важны, то либо используйте сообщение "ping" на уровне приложения, чтобы время от времени отправлять данные между одноранговыми узлами или использовать TCP keep-alive. Лично я бы пошел за сообщениями ping...

Изменить: Конечно, все, что предполагает, что вы хотите узнать, можете ли вы по-прежнему отправлять данные по соединению, в конце концов, вы TOLD, когда клиент больше не отправляет, потому что вы читаете будет возвращать 0 байтов, и вы ЗНАЕТЕ, когда он отключит свою сторону отправки, потому что ваши записи будут сбой; вы также ЗНАЕТЕ, когда вы завершаете либо отправку, либо recv-сторону вашего собственного конца соединения...

Я предполагаю, что я должен был застрять с реакцией реакции начального кишечника "define disconnected";)

Ответ 3

Существует несколько разных способов, но наиболее распространенным является проверка результата команды отправки или получения:

 nReadBytes = recv(sd, ReadBuffer, BufferSize, 0);
 if (nReadBytes == SOCKET_ERROR)
 {
     //error
 }
 nSendBytes = send(sd, WriteBuffer, BufferSize, 0);
 if (nSendBytes == SOCKET_ERROR)
 {
     //error
 }

Дополнительные примеры (в комплекте с проверкой ошибок, как клиент, так и сервер):

http://tangentsoft.net/wskfaq/examples/basics/

Ответ 4

Если результатом send() или recv() является SOCKET_ERROR и WSAGetLastError() возвращает WSAECONNRESET, клиент отключился.
Из MSDN:

WSAECONNRESET

Соединение reset с помощью однорангового узла.

Существующее соединение было принудительно закрыто удаленным хостом. Эта обычно получается, если одноранговое приложение на удаленном хосте внезапно остановился, хост перезагружен, хост или удаленная сеть интерфейс отключен, или удаленный хост использует жесткое закрытие (см. setsockopt для получения дополнительной информации о опции SO_LINGER на пульте дистанционного управления разъем). Эта ошибка может также возникнуть, если соединение было нарушено из-за активная активность, обнаруживающая сбой при выполнении одной или нескольких операций продолжаются. Выполненные операции заканчиваются неудачей WSAENETRESET. Последующие операции не выполняются с помощью WSAECONNRESET.

Это также работает с неблокирующими сокетами.

int r = recv(sock, NULL, 0, 0);
if(r == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET){
    //client has disconnected!
}