I am attempting to write a server application in C on a linux machine which listens for TCP connections and transfers data. I am trying to detect on the server side when the connection is broken. The closest thing that I got to work was looking at the return value from sending data. For example the server’s job is to mainly read data from the socket but also sends data back to the client periodically to test if the connection is still up. I look at the return value from send() to determine if the connection is broken e.g.
I found that this does not immediately return an error when the connection is broken. The reason for this is because even though the connection is broken send() is still successful because it is able to put it on the network buffer. To fix the issue I did the following things;
int ret = send(session->clientSocket, &data[sentCnt], count - sentCnt, MSG_NOSIGNAL);
Setting the timeout and the buffer should ensure that the socket will timeout if the data sent is more than 2 bytes and the connection is broken.
//set send timeout
struct timeval timeout;
timeout.tv_sec = 4;
timeout.tv_usec = 0;
//apply send timeout socket options
setsockopt(tcp->socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval));
//set output buffer size so that send blocks
int buffersize = 2;
setsockopt(tcp->socket, SOL_SOCKET, SO_SNDBUF, &buffersize, 4);
I have tested this and it worked i.e. when i pull the plug from the modem the server detects that the conneciton is broken fairly quickly.
The server runs as a virtual machine somewhere in the US and the client which im using to test is in Sydney Australia. I tested the client on my Telstra cable connection and it worked. I also tested on my Optus 3G wireless broadband connection and it also worked. The problem is however when I tested on my Telstra 3G wireless broadband and it DID NOT work. The server was happily thinking that it was sending data to the client when the client was well and truly disconnected from the internet. I had swaped modems and simcards around isolated the problem down to the network provider i.e. works on Telstra cable and Optus 3G but not on Telstra 3G.
How can the server think that it’s successfully sent data to the client which is not connected to the internet, I thought TCP was in end to end protocol.
Does anyone have any idea why this occurs or how else i can go about doing this?