简体   繁体   中英

How can I check if a client disconnected through Winsock in C++?

如何检查客户端是否通过C ++中的Winsock断开连接?

Beej's Network Programming Guide

if you call recv in blocking mode and it returns with 0 bytes read, the socket has disconnected, else it wait for bytes to be received.

Look in this FAQ 2.12

example from select on this page.

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

You can only tell if a TCP socket is 'disconnected' by attempting to send data. This is because the design of the protocol is such that it's supposed to allow for temporary outages between peers. So, if you connect from A via R1 via R2 via R3 to B and send data for a while and then stop sending you could unplug R2->R3 (for example) and neither A nor B would notice (or care). If you then plugged R2->R4 and R4->R3 and then tried to send data between A and B then things would 'just work' and you'd never know. If, however, you tried to send data when R2->R3 was disconnected then you'd (eventually, after all the TCP level retries) get an error back.

Now, some operating systems may be able to alert you to the fact that your local network adapter isn't currently connected and you could use that to say "I'm no longer connected to my peers" but I wouldn't advise it.

If having your peers know when connections are 'broken' is important then either use an application level 'ping' message to occasionally send data between the peers or use TCP keep-alive. Personally I'd go for the ping messages...

Edit: Of course all that is assuming that you want to know if you can still send data on a connection, after all, you're TOLD when the client is no longer sending because your reads will return 0 bytes and you KNOW when it disconnects its send side because your writes will fail; you also KNOW when you shutdown either the send or recv side of your own end of the connection...

I guess I should have stuck with initial gut reaction response of "define disconnected" ;)

There are a few different ways, but the most common is to check the result of a send or receive command:

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

More examples (complete with error checking, both client and server) here:

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

If the result of send() or recv() is SOCKET_ERROR and WSAGetLastError() returns WSAECONNRESET the client has disconnected.
From MSDN:

WSAECONNRESET

Connection reset by peer.

An existing connection was forcibly closed by the remote host. This normally results if the peer application on the remote host is suddenly stopped, the host is rebooted, the host or remote network interface is disabled, or the remote host uses a hard close (see setsockopt for more information on the SO_LINGER option on the remote socket). This error may also result if a connection was broken due to keep-alive activity detecting a failure while one or more operations are in progress. Operations that were in progress fail with WSAENETRESET. Subsequent operations fail with WSAECONNRESET.

This also works with non blocking sockets.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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