简体   繁体   中英

Detecting disconnected client side socket connection (cross-platform applicability)

I know there are hundreds of answers for this question, but I cannot get it done with respect to my situation. The scenario is like this, we have a server written in TCP/IP protocol, we have multiple clients connected to this server. The client here is a software module which before starting on a client machine, registers its presence in the server and loads the functionalities. But the problem is that this software module getting crashed and there by no socket.close() is called, this will make its footprints still present in the server even though its crashed. How to recognize this?

I am using select() method in the client to notify any info from client and server (vice-versa) I cannot create a process separately for each client request in the server, neither can I create a parent-child mechanism in the client machine. tcp-keepalive is not applicable as we need to tweak the registry in Windows? I need a x-platform compatible solution. I have read that recv() to the connected socket in the server code will return some values from 'that' client such as 0 for socket closed? Can I use this to clear off the client socket registration in the server database? Will this work?

You didn't specify what method you are using to handle socket events in your server side code. Whatever method for polling your sockets you are using, recv() will return 0 or possibly -1/ SOCKET_ERROR when a client crashes.

To detect inactive client connections most server applications send out some form of heartbeat or ping message periodically within the application layer protocol. When an ACK fails to be sent from the client the server application will then get notification the client disconnected via recv() returning 0 or SOCKET_ERROR with an error code of something like WSAENETRESET , WSAECONNABORTED , WSAETIMEDOUT , or WSAECONNRESET (see the various error codes here ). Often after the server sends the heartbeat to a client TCP port that is no longer active an ICMP packet is sent in response that will alert your server that the port or host not active ( recv() will immediately notify you of this event).

If you wish to turn the TCP keep alive timer on you can use the socket option SO_KEEPALIVE . The interval can also be set using SIO_KEEPALIVE_VALS .

Edit: Keep in mind the various error codes and option SIO_KEEPALIVE_VALS are Win32 specific. To handle these events for other operating systems you will need to use operating specific ways of retrieving error codes and setting the TCP keep alive interval if you choose to do so. My best suggestion to keeping your code cross platform compatible is to simply implement an application layer heartbeat message into your protocol or some other application layer specific timeout. Doing so will allow you to forget about managing TCP keep alives.

Update

I cannot comment on EJP's answer, but it's important to point out that by calling send() he is effectively recommending you implement a heartbeat/ping message in the application layer of your protocol. While checking the return value of send() is important, if you are polling/selecting read events you will be notified of the TCP connection being disconnected immediately upon calling recv() the moment the connection is deemed broken by the TCP stack. If you wait for your application timer to try to send some data using send() that could be many seconds (depending on the length of your interval timer) after recv() has already notified you that the connection is broken. In other words: pay attention to the recv() return values as well as your send() return values.

tcp-keepalive is not applicable as we need to tweak the registry in Windows?

TCP keepalive is an option if you can accept the default timeout of two hours.

I need a x-platform compatible solution.

TCP keepalive is cross-platform.

I have read that recv() to the connected socket in the server code will return some values from 'that' client such as 0 for socket closed?

it will return zero if the peer closes its socket, and on some platforms if the peer process merely exits without closing it.

Can I use this to clear off the client socket registration in the server database? Will this work?

Only if you can rely on the peer closing the socket properly.

It seems to me that what you should be doing is debugging the client code so it doesn't crash, and using TCP keepalive as a long-term backup.

You should also be aware that send() to a peer that has exited will sooner or later fail with an ECONNRESET error.

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