ultimate cause
ultimate cause

Reputation: 2294

Behaviour of recv on a non-blocking TCP socket before connection completion

Friends,

I have a non-blocking TCP socket (on AIX). When I attempted connect() I got EINPROGRESS. My question is if I call recv() before connection completion, what would be the (most apprpriate) error code?

I saw that, in case connection fails, and I call recv(), I got ECONNREFUSED; means I got an error corresponding to my earlier connect() attempt. Taking same logic I should get EINPROGRESS for recv(). Am I right in my approach ?

If yes, this raises another question - Why such error codes are not included amongst error codes of recv()?

Upvotes: 1

Views: 2701

Answers (2)

fluter
fluter

Reputation: 13786

You are operating on a non-blocking socket, which is perfect fine to return EINPROGRESS, which indict that the connection establishment has not being finished yet, this is documented in connect's page:

   EINPROGRESS
          The  socket  is  nonblocking  and  the  connection cannot be completed immediately.  It is possible to select(2) or poll(2) for completion by
          selecting the socket for writing.  After select(2) indicates writability, use getsockopt(2) to read the SO_ERROR option at  level  SOL_SOCKET
          to  determine  whether connect() completed successfully (SO_ERROR is zero) or unsuccessfully (SO_ERROR is one of the usual error codes listed
          here, explaining the reason for the failure).

So you will need select/pool to make sure the socket is writable, and get error from SO_ERROR.

Upvotes: 1

nickm
nickm

Reputation: 496

I have only seen EAGAIN returned in this case, just as you would see in the case where there's no data to read. For writing to a non-connected socket, you typically get ENOTCONN, though I believe some platforms might give you EAGAIN.

Here's a trivial Python script to demonstrate:

import socket
# Any address that does not succeed or fail right away will do
ADDR = "192.168.100.100"
PORT = 23
s = socket.socket()
s.setblocking(False)
try:
    s.connect((ADDR, PORT))
except socket.error, e:
    print "Connect gave us",e
try:
    s.recv(1)
except socket.error, e:
    print "Read gave us",e
try:
    s.send("x")
except socket.error, e:
    print "Write gave us",e

For me, it gives: Connect gave us (36, 'Operation now in progress') Read gave us (35, 'Resource temporarily unavailable') Write gave us (57, 'Socket is not connected')

These are EINPROGRESS, EAGAIN, and ENOTCONN respectively.

Upvotes: 3

Related Questions