3

I'm trying to implement a simple client/server program on linux using TCP and the standard socket.h library. server handling multiple clients and each client can close() or shutdown() the socket any time he wants.

on the server side (using a non blocking read):

int nBytes;
if ((nBytes = recv(socket, buffer, BUFFER_SIZE, MSG_DONTWAIT)) == -1)
{
    if (errno != EAGAIN && errno != EWOULDBLOCK)
    {
        //print to log
    }

}
if (nBytes == 0)
{

    //other side closed the connection
}

I'm getting recv() returning -1 and error set to ECONNRESET. If the client has closed the connection shouldn't recv() return 0?

susdu
  • 852
  • 9
  • 22

3 Answers3

11

There are numerous causes, including but not limited to:

  • the peer deliberately reset the connection
  • the peer closed the connection while he still had unread data pending
  • you had sent data to a connection that had already been closed by the peer
  • you had pending write data and the TCP retries have timed out
  • TCP keepalive detected a lost connection.

This is a fatal error, and you should close the socket when you get it.

each client can close() or shutdown() the socket any time he wants.

No he can't. See above.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • I wonder why this critical fatal error isn't mentioned in the recv man – susdu Jan 29 '16 at 21:15
  • 2
    @susdu This error condition is mentioned in the official X/Open documentation at : The recv() function shall fail if: ... [ECONNRESET] A connection was forcibly closed by a peer. – Steve Emmerson Jan 30 '16 at 17:11
  • 1
    @susdu 'Additional erros may be generated by the protocol layers ...' – user207421 Jan 31 '16 at 11:50
4

If the remote peer has cleanly closed the connection, and there are no more bytes waiting to be read on the local end, then yes, recv() should return 0. So if you get an ECONNRESET then it's reasonable to assume that an orderly closure is not what has happened.

An ECONNRESET often indicates that the remote peer sent a RST packet without having first closed the connection cleanly. There are many reasons why this might happen. Alternatively, as EJP observed, a reset may originate locally, too.

In any event, after an ECONNRESET it's not reasonable to suppose that you will be able to read anything further from the socket, so in your particular case you should probably handle it much the same as way as you handle recv() returning 0, +/- logging.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
3

You may get ECONNRESET if client closed his side without reading sent data. If he closed connection properly you'll get 0.

sheikh_anton
  • 3,422
  • 2
  • 15
  • 23