You could use threads, but it would introduce unnecessary overhead for this task.
Use non-blocking sockets here (and avoid non-blocking sockets wherever you can! really, but they make sense in this case):
// initiate tcp connects...
for( each of your target host+port pairs ) {
int socket = socket( AF_INET, SOCK_STREAM );
...
#ifdef WIN32
unsigned long mode = 1;
ioctlsocket( socket, FIONBIO, &mode );
#else
int value = fcntl( socket, F_GETFL, 0 );
fcntl( socket, F_SETFL, value | O_NONBLOCK );
#endif
...
int code = connect( s, target, ... );
if( code == 0 ) { /* ok, this one did connect, DONE */ }
// now remember the socket in a list ...
}
// now find the first socket that was successfully connected
while( still not found ) {
struct timeval tval;
memset( &tval, 0, sizeof(tval) );
fd_set write_set, error_set;
int largest_socket = 0;
// add sockets to write and error set, and determine largest socket no.
for( each socket that did not fail until now ) {
FD_SET( socket, write_set );
FD_SET( socket, error_set );
if( socket > largest_socket ) largest_socket = socket;
}
// now use select to wait until something happens on the sockets
int code = select( largest_socket+1, NULL, &write_set, &error_set, &tval );
if( code < 0 ) { something went terribly wrong }
else {
for( each socket that did not fail until now ) {
if( FD_ISSET( socket, write_set ) ) { you've found it! DONE }
if( FD_ISSET( socket, error_set ) ) { error, remove this socket from list (for next iteration) }
}
}
}
Check documentation for connect
and select
for more details!