Question

I have a client-server application where each side communicate with the other via TCP socket.

I properly establish the connection and then I crash the server BEFORE any data is written on the socket by the client.
What I see is that the first write() attempt (client-side) is successful and it returns the actual number of written bytes, while the following ones return (as I expected) -1 (receiving a SIGPIPE) and errno=EPIPE.

Why the first write() is successful even if the socket is already closed?

EDIT Sometimes also the following write() have a positive return values, as if everything goes well.

Was it helpful?

Solution

You're confused by what the return value of write() means. It doesn't mean, "the peer got the data and acknowledged it". Instead, it means, "I buffered so-many bytes to send to the peer and they're my responsibility now, so you can forget about them (and I don't have any pending errors)".

That is, if the TCP stack accepts the write and returns n bytes, that doesn't mean they've been written yet, just queued for writing. It'll take some time, perhaps 30s after it starts sending network traffic, before the stack gives up and returns an error to you. During that time, you could have done several calls to write() which were successful at queueing data for sending. (The write error will be returned in c.30s if the peer has vanished, or immediately if the peer can be contacted and sends a RST packet straight away to indicate the connection is dead.)

OTHER TIPS

This has to do with how TCP/IP works, that can be roughly described as two mostly independent half-connections. When you close the socket at the server, the client is told that it will not receive further data from the C<-S half-connection, waking up read() immediatly, but not about the C->S direction. It only gets a reply resetting the connection after it tries to send some data. I recommend the TCP/IP Guide for further details.

The reason why sometimes you can write() twice is that you write faster than the round-trip time and can squeeze a second write() before the reply to the first one.

I'm using the following method to detect a disconnected server condition:

After getting the select() timeout on a socket (nothing was received, though was supposed to), the 'system("ping -c 1 -w 1 server");' command is activated. If the server is up and just lagging, the ping command will return in less than 0.1 seconds. Otherwise (the server is down), the ping command will return in 1 second.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top