s = socket(AF_INET, SOCK_STREAM, 0);
fcntl(s, F_SETFL, FNDELAY);
if (connect(s, &sin, sizeof sin) < 0 && errno != EINPROGRESS)
perror("connect");
... select on s for writing and do other stuff until s is ready
... for writing
getsockopt(s, SOL_SOCKET, SO_ERROR, &err, sizeof(err));
if (err != 0) {
errno = err;
perror("connect");
} else {
/* Connection succeeded */
}
The getsockopt(..., SO_ERROR, ...) gets me the errno from the
connect(), e.g. ETIMEDOUT, EHOSTUNREACH, or whatever. On Solaris, the
getsockopt() returns -1/EPIPE if the connect() failed. I work around
this right now by setting err to ENOTCONN if the getsockopt() fails, so
that it prints a vaguely generic error message, but I'd like to be able
to return the real error even under Solaris. Does anyone know how to
do this?
Thanks,
Bill
In article <4re7o3$6...@news.parc.xerox.com>,
Bill Fenner <fen...@parc.xerox.com> wrote:
>
> s = socket(AF_INET, SOCK_STREAM, 0);
> fcntl(s, F_SETFL, FNDELAY);
> if (connect(s, &sin, sizeof sin) < 0 && errno != EINPROGRESS)
> perror("connect");
> ... select on s for writing and do other stuff until s is ready
> ... for writing
if (getsockopt(s, SOL_SOCKET, SO_ERROR, &err, sizeof(err)) < 0) {
#ifdef SOLARIS
switch (errno) {
/*
* Solaris 2.4's socket emulation doesn't allow you
* to determine the error from a failed non-blocking
* connect and just returns EPIPE. Create a fake
* error message for connect.
*/
case EPIPE:
err = ENOTCONN;
break;
/*
* Solaris 2.5's socket emulation returns the connect
* error as a getsockopt error. If getsockopt returns
* an error that could have been returned by connect,
* use that.
*/
case ENETDOWN:
case ENETUNREACH:
case ENETRESET:
case ECONNABORTED:
case ECONNRESET:
case ENOBUFS:
case EISCONN:
case ENOTCONN:
case ESHUTDOWN:
case ETOOMANYREFS:
case ETIMEDOUT:
case ECONNREFUSED:
case EHOSTDOWN:
case EHOSTUNREACH:
case EWOULDBLOCK:
case EALREADY:
case EINPROGRESS:
err = errno;
break;
/*
* Otherwise, it's probably a real error.
*/
default:
perror("getsockopt");
return;
}
#else
perror("getsockopt");
return;
#endif
}
> if (err != 0) {
> errno = err;
> perror("connect");
> } else {
> /* Connection succeeded */
> }
It's possibly safe to eliminate the case, and just pretend that connect
returned the error if getsockopt() returns any error; I just wanted to
reduce the possibility of weird problems being incorrectly reported.
Bill