Blocking connect() fails, non-blocking succeeds?

Blocking connect() fails, non-blocking succeeds?

Post by Eric Winte » Tue, 11 Feb 1997 04:00:00



Hi folks.

        I'm experiencing an odd problem using a non-blocking connect() call. Our
code is vanilla in this respect - it uses fcntl() to set the non-blocking
bit, etc., and the code works fine. However, during testing, we tried
running the code against machines on the net which are not listening at the
standard ports for our application. We expected that this would cause our
background connection attempts to fail, which we would detect by periodic
select() calls to see if the socket is writable. However, this non-blocking
connect() call _always_ seems to succeed when run against a valid host
which does not have our server running. To further confuse the issue, when
we vary the port number, it seems that the non-blocking connect() _always_
succeeds. Also, when we use a _blocking_ connect call to the same address
and port, we get (again, as expected), a -1 returned from connect, with
errno = ECONNREFUSED.

        The problem is, our code sends a message to the server when the connection
is "established", i.e. when select() indicates the socket is writable.
However, such a socket isn't writable, really - there is no server at the
other end. As you might expect, when we send the message, we get a SIGPIPE,
which we catch, so our program doesn't crash.

        Am I missing something here? I thought the point of using a non-blocking
connect() was to put it in the background. Is there some other step that
must be taken in order to ensure that the connection has been established?

        Any help or ideas appreciated.

Eric Winter
Hughes STX

 
 
 

Blocking connect() fails, non-blocking succeeds?

Post by Eric Winte » Tue, 11 Feb 1997 04:00:00


I may have answered my own question here (read the FAQ, but didn't pay
enough attention to it :^():

Could this problem arise because the TCP layer at the destination address
has done its listen() and "heard the call", but has not yet processed it
with an accept(), if any? My guess is that the TCP layer at the destination
opens a socket for the incoming connection, completes the SYN, then says to
itself "Uh-oh - I don't have a server set up to handle this requests at
this port. Better cut this off." - and does so. So in essence, the
non-blocking connect() will always succeed end up with select() saying the
socket is writable, even though a real connection to the desired server has
not been established. So I guess I need to check somehow that the desired
server has indeed been contacted before I send the message.

How does this sound?

Eric Winter



Quote:> Hi folks.

>    I'm experiencing an odd problem using a non-blocking connect() call. Our
> code is vanilla in this respect - it uses fcntl() to set the non-blocking
> bit, etc., and the code works fine. However, during testing, we tried
> running the code against machines on the net which are not listening at
the
> standard ports for our application. We expected that this would cause our
> background connection attempts to fail, which we would detect by periodic
> select() calls to see if the socket is writable. However, this
non-blocking
> connect() call _always_ seems to succeed when run against a valid host
> which does not have our server running. To further confuse the issue,
when
> we vary the port number, it seems that the non-blocking connect()
_always_
> succeeds. Also, when we use a _blocking_ connect call to the same address
> and port, we get (again, as expected), a -1 returned from connect, with
> errno = ECONNREFUSED.

>    The problem is, our code sends a message to the server when the
connection
> is "established", i.e. when select() indicates the socket is writable.
> However, such a socket isn't writable, really - there is no server at the
> other end. As you might expect, when we send the message, we get a
SIGPIPE,
> which we catch, so our program doesn't crash.

>    Am I missing something here? I thought the point of using a non-blocking
> connect() was to put it in the background. Is there some other step that
> must be taken in order to ensure that the connection has been
established?

>    Any help or ideas appreciated.

> Eric Winter
> Hughes STX


 
 
 

Blocking connect() fails, non-blocking succeeds?

Post by Andrew Giert » Wed, 12 Feb 1997 04:00:00


 [problems with non-blocking connect]

 Eric> Could this problem arise because the TCP layer at the
 Eric> destination address has done its listen() and "heard the call",
 Eric> but has not yet processed it with an accept(), if any? My guess
 Eric> is that the TCP layer at the destination opens a socket for the
 Eric> incoming connection, completes the SYN, then says to itself
 Eric> "Uh-oh - I don't have a server set up to handle this requests
 Eric> at this port. Better cut this off." - and does so.

No, that isn't how it works. The desticnation system replies with RST
to incoming SYNs if there is no listening socket - it doesn't complete
the SYN.

The precise answer you're looking for isn't in the FAQ yet, so here goes:

When you call connect() on a socket in non-blocking mode, there are
effectively 3 possible outcomes: the connect can immediately succeed,
it can immediately fail, or it returns EINPROGRESS.

When connect() returns with EINPROGRESS, the connection attempt has been
started. The usual method for detecting when the attempt completes is to
call select(), testing for *writability* of the socket. *But*, the socket
selects as writable *regardless* of whether the connection succeeded or
failed; there is a general rule with select() that error conditions always
cause the socket to return 'ready'.

I've seen several methods suggested to get the connect() error code:

  - call getsockopt(SO_ERROR), but there is a gotcha here; some systems
    return the error code in the value parameter, others actually make
    the getsockopt() call fail with the stored errno

  - call read() with a length of 0

  - call getpeername()

  - call connect() again

If you are selecting for readability as well as writability on the socket,
then a failed connect causes the socket to show ready for *both* read and
write, and a read() call will return the connect() error.

HTH

--
Andrew.

 
 
 

Blocking connect() fails, non-blocking succeeds?

Post by Shado » Sat, 15 Feb 1997 04:00:00



Quote:>non-blocking connect() will always succeed end up with select() saying the
>socket is writable, even though a real connection to the desired server has
>not been established. So I guess I need to check somehow that the desired
>server has indeed been contacted before I send the message.

>How does this sound?

I recall seeing some code which had a table showing what select() would
return on a non-blocking connect on various OSs, at that time I just
figured "hey this unportable". But then i came across something more
interesting:

/usr/include/sys/socket.h:#define SO_CONNECT      3

you can do a getsockopt for it.. on the SOL_SOCKET level, and see if the
OS thinks its connected or not. Do this _after_ you get it back from
select, that still doesnt solve the problem if its actually connected yet
or not. But it tells you for sure what your OS thinks, my guess is
select() return writable, but it doesnt neccaserly mean its connected.
Again writable might mean "this socket is has returned from a call",
where SO_CONNECT might tell u if it is or it isnt connected.

I dare not give exact facts here as in "it works like this". Too many OSs
do these undefined things differently; I havent seen any documentation
anywhere documenting the select return of a non-blocking connect.

Test it out and good luck.

------------------------------------------------------------------------------
Thamer Al-Herbish (ShadowS)     The views expressed here, have no relevance


              "illegitimi non carborundum"
-------------------------------------------------------------------------------

 
 
 

Blocking connect() fails, non-blocking succeeds?

Post by Andrew Giert » Sat, 15 Feb 1997 04:00:00


 ShadowS> I recall seeing some code which had a table showing what
 ShadowS> select() would return on a non-blocking connect on various
 ShadowS> OSs, at that time I just figured "hey this unportable". But
 ShadowS> then i came across something more interesting:

 ShadowS> /usr/include/sys/socket.h:#define SO_CONNECT 3

 ShadowS> you can do a getsockopt for it.. on the SOL_SOCKET level,
 ShadowS> and see if the OS thinks its connected or not.

Have to disappoint you - that doesn't exist on the BSD implementation,
nor, for that matter, on any of the other systems I'm familiar with.

--
Andrew.