How do you handle connect() errors? Suppose you are writing a simple TCP client application using standard sockets API, therefore you do (without error checking):
int sock; /* Socket descriptor */
struct sockaddr_in sa; /* Server address */
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
die("socket() failed");
bzero(&sa, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr("74.125.77.147");
sa.sin_port = htons(80);
if (connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
die("connect() failed");
<...>
This should work quite well, but what if you don’t want your app to die when connect() fails? Can you repeat connect() call, or do you have to close() the socket? Man pages are not very helpful in this case:-( Linux man page doesn’t contain anything relevant, nor does FreeBSD man page. The first hint we can find in X/Open standard:
http://pubs.opengroup.org/onlinepubs/009695399/functions/connect.html
There is again nothing in required sections, but in informative section Application Usage we find:
If connect() fails, the state of the socket is unspecified. Conforming applications should close the file descriptor and create a new socket before attempting to reconnect.
So this seems that if you are writing portable applications (and you are, right?), you should close() the socket in case connect() returns any error. Is this really necessary? Solaris connect(3socket) man page says for ECONNREFUSED error code:
ECONNREFUSED The attempt to connect was force-
fully rejected. The calling program
should close(2) the socket descrip-
tor, and issue another
socket(3SOCKET) call to obtain a new
descriptor before attempting another
connect() call.
This is only a recommendation, and only for one error code, so again nothing relevant. But finally connect(3xnet) man page says:
USAGE
If connect() fails, the state of the socket is unspecified.
Portable applications should close the file descriptor and
create a new socket before attempting to reconnect.
So in case you are using libxnet library for sockets implementation it’s clear – you have to close() the socket on any error, because you cannot work with socket in unspecified state. But it doesn’t matter which library you are using, does it? Both of them uses the same syscall for connect operation, and therefore the kernel behavior would be the same in both cases, right? So we have a result:
On Solaris you have to close() the socket every time connect() returns any error code.
I am not sure about behavior of other systems, but I would be afraid it’ll be the same in all cases. So close() your sockets rather every time.