Hi, All. I am a new Linux programmer. I made a Linux TCP server for control applications. When some TCP client connects to it, goes into infinite console loop, getting characters, echoing them to client, parsing commands etc. Everything is OK until the client unexpectedly terminates the connection. I have to detect this event inside the loop and break. I thought that it might be done by analyzing socket state (i.e. if the state is not ESTABLISHED - break the loop) but from various examples and HOWTOs I did not see how to do it. It seems that I have to solve this problem in different way. Can anybody criticize and prompt? Regards, Alex.
Do yourself a favor: never write your own socket code. Make your employer buy _UNIX Network Programming_ by W. Richard Stevens, Volumes One and Two. Read the books when you can; use it as a cookbook in the meantime. Your computer will love you for it.
While you're at it, you should also consider getting _The Art of Computer Programming_ Volumes 1-3 by Donald E. Knuth. Understanding all of what's in these three books will make you a better programmer than 99.9% of those who are actually programmers.
This question is of interest to me as well, and I can see that no one here has the answer. I haven't been doing much with Linux but there is a "keepalive" option implemented in some TCP stacks to make sure the connection is still active. You might want to research that.
An approach I am looking at using is to do a recv with timeout. If nothing comes and the recv times out then I will send data to the other connected socket. I am expecting that a blocking send will fail if the connected socket no longer exists. The problem is that while sitting in recv and the other end is idle that there is no way to differentiate between a dead or idle connection. Periodic sends of dummy data should reveal that the connected socket is dead if there is no ack on the sent data.
Hi, FLY135, I read that keepalive really tests the integrity of Ethernet connection and returns ENETRESET error if the connection is terminated but I read that the timeout is 2 (in other articles - 4) hours. The point really is that the operator may be idle for hours and it is to be acceptable. Though, I haven't read Knuth yet :-).
There are two ways that the server can see that the connection has gone away. First, a negative return on read() which is not EWOULDBLOCK. Second, include the socket in your list of error file descriptors which you pass to select(). If it indicates an error, the socket is likely gone (you might want to be more discriminating on errors; I'm not).
The other problem is that TCP may not notice that the socket has gone away for quite a long time. This is the case when you have nothing outstanding to be acked (by the client) when the session goes away and no attempt to send anything from the server until you get something from the client (which can no longer happen). This is what the TCP keepalives are for. They are on by default in most TCP implemenations but they tend to be in the 2 hour range. So a "poll" is only sent to the client every 2 hours and it isn't until then that you don't get a reponse and then get the session failing (and the read() failing or the exception indication). This is fine for things like telnet which are using a not very scarce resource (pseudo ttys). I set the timeout to about 2 minutes for connections:
on = 1; setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof(on)); value = 2 * 60; /* every 2 minutes */ setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, (char *)&value, sizeof(value));
Here on and value are ints.
As a side benefit if you are using a VPN, Cisco IOS times out idle sessions every hour. If you happening to be going through a Cisco and using VPN, the keepalives are considered traffic enough that Cisco doesn't see them as idle (defeating Cisco's idle feature, but of more use to my application).
Regards, Steve
------------------------------------------------------------------------ Steve Schefter phone: +1 705 725 9999 x26 The Software Group Limited fax: +1 705 725 9666
ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here.
All logos and trade names are the property of their respective owners.