From: hawkeye@glia.biostr.washington.edu (Ken Keys - TF Dude)
Newsgroups: comp.unix.programmer
Subject: Re: asynchronously connecting a socket
Date: 12 Jan 93 00:44:35 GMT
Article-I.D.: glia.hawkeye.726799475
Organization: University of Washington
NNTP-Posting-Host: glia.biostr.washington.edu

In <1icau7INNg7f@grasp1.univ-lyon1.fr> Christophe.Wolfhugel@grasp.insa-lyon.fr (Christophe Wolfhugel) writes:

>The connect(3n) system call when used aynchronously will return -1 with
>errno set to EINPROGRESS.  A write select(3n) will indicate completion
>of the connect.  Is this an option or is it mandatory ?

>In order to check return codes, I used a small loop:

>      while (connect(f->f_file, &ip, sizeof ip) < 0) {
>         fprintf(stderr, "errno = %d\n", errno);
>         sleep(1);
>         continue;
>      } /* endif */

>This returns:

>errno = 150 (EINPROGRESS)
>errno = 11 (EAGAIN)
>[many other errno = 11]
>Broken pipe

>and the application dies.  Is this behavior illegal (I know it does not
>make much sense to have such a loop).  Shouldn't I get a EALREADY
>instead of the EAGAIN ?

>Also, in a select loop.  Once select indicates a write even for that
>file description.  How do I check the connection ?  Redo a connect()
>and except errno to be either EISCONN to indicate success, any other
>result to indicate failure ?

>-- 
>Christophe Wolfhugel    |    Email: Christophe.Wolfhugel@grasp.insa-lyon.fr

According to my man pages (on BSDi and IRIX), connect() should set errno
to EALREADY if a connection is already in progress.  EAGAIN is not listed
as one of the possible errno values.  But I have seen systems which can
use EAGAIN in this situation, so be prepared to deal with it.

The biggest problem is finding out when the connection is ready.  The
man pages claim that it is ready when the socket selects true for
writing.  But I've seen systems where select *always* return true for
writing, so if you're trying to write portable code, this won't work.
Even if select is correct, you must test the socket to see if the
connection worked.  A second connect() will set errno=EISCONN if the
first one worked, and anything else indicates failure; however, there
is no way of finding out *why* the original nonblocking connect() failed.

A more robust way of doing asynchronous connections is by using a
seperate process as a connection server.  When a (client) process needs
a connection, the server does a blocking connect() call.  When the call
returns, the server passes either an error number or the open file
descriptor back to the client.  Of course, your system must support
open file descriptor passing (SVR4, BSD "4.3+", and other "modern"
systems support this).  I implemented this method myself by having the
client create a child process for each connection it needed.  The
client could select on the pipe(s) to the process(es) to determine when
a connection had succeeded or failed.  The book _Advanced Programming
in the UNIX Environment_ by W. Richard Stevens contains an excellent
description of this method.

--
Ken Keys, aka Hawkeye
Master of the Fugue
kkeys@ucsd.edu or hawkeye@ucsd.edu
-- 
--
Ken Keys, aka Hawkeye
Master of the Fugue
kkeys@ucsd.edu or hawkeye@ucsd.edu
Newsgroups: comp.unix.programmer