The second more general way to make a connect call time-out is to make the socket nonblocking, and then wait for it to complete with select. This approach avoids many of the problems encountered when using alarm, but we must admit that there are many portability issues with this approach, even in UNIX implementations.
int main (int argc, char **argv)
{
Fd_set rdevents;
Fd_set wrevents;
Fd_set exevents;
struct SOCKADDR_IN peer;
struct Timeval TV;
SOCKET s;
int flags;
int RC;
INIT ();
Set_address (Argv[1], argv[2], &peer, "TCP");
S=socket (af_inet,sock_stream,0);
if (!isvalidsock (s))
Error (1,errno, "socket call failed");
if ((Flags=fcntl (s,f_getfl,0)) <0)
Error (1,errno, "Fcntl (F_GETFL) failed");
if (rc = connect (s, struct sockaddr *) &peer,
sizeof (peer)) && errno! = einprogress)
Error (1,errno, "Connect Failed");
if (rc = = 0)
{
if (Fcntl (S,f_setfl,flags) < 0)
Error (1,errno, "fcntl (Restore Flags) failed");
Client (S,&peer);
EXIT (0);
}
Fd_zero (&rdevents);
Fd_set (s,&rdevents);
Wrevents = rdevents;
Exevents = rdevents;
Tv.tv_sec = 5;
tv.tv_usec = 0;
rc = Select (S+1, &rdwvents, &wrevents, &exevents, &TV);
if (RC < 0)
Error (1,errno, "select Failed");
else if (rc = = 0)
Error (1,0, "Connect timed out\n");
else if (isconnected (s,&rdevents, &wrevents, &exevents))
{
if (Fcntl (s, F_SETFL, flags) < 0)
Error (1 errno, "fcntl (Restore Flags) failed");
Client (S,&peer);
}
Else
Error (1,errno, "Connect Failed");
EXIT (0);
}
int isconnected (SOCKET s,fd_set *rd, Fd_set *wr, Fd_set *ex)
{
int err;
int len=sizeof (ERR);
errno = 0;
if (! Fd_isset (S, RD) &&! Fd_isset (S, WR))
return 0;
if (getsockopt (S,sol_socket,so_error,&err,&len) < 0)
return 0;
errno = err;
return err = = 0;
}
How the Connect call time-out is implemented