views:

558

answers:

4

I'm using sockets in c++ on linux to connect to a server using connect(), but it doesn't seem to have a timeout value. What would be the easiest/best way to give it a timeout of a few seconds. I'll post the code I have up to, and including, the blocking call to connect():

using namespace std; int main( int argc, char* argv[] ) { // Interpret the command line arguments string uri_string = "";
if ( argc != 2 )
{
 cerr << "Usage: " << argv[0];
 cerr << " <URI>" << endl;
 return 1;
}
else
{
 uri_string = argv[1];
}

// Create URI object and have it parse the uri_string
URI *uri = URI::Parse(uri_string);

if ( uri == NULL )
{
 cerr << "Error: Cannot parse URI." << endl;
 return 2;
}

// Check the port number specified, if none use port 80
unsigned port = 80;
if ( uri->Is_port_defined() )
{
 port = uri->Get_port();
}

// Create TCP socket and connect to server
int tcp_sock = socket( AF_INET, SOCK_STREAM, 0 );
if ( tcp_sock < 0 )
{
 cerr << "Unable to create TCP socket." << endl;
 return 3;
}

sockaddr_in server;
socklen_t slen = sizeof(server);

server.sin_family = AF_INET;
server.sin_port = htons( port );
cout << "Resolving " << uri->Get_host() << "... ";
hostent *hostp = gethostbyname( uri->Get_host().c_str() );
memcpy( &server.sin_addr, hostp->h_addr, hostp->h_length );

struct in_addr **pptr;
pptr = (struct in_addr **)hostp->h_addr_list;

string ip_addr = "";
while( *pptr != NULL ) {
 ip_addr += inet_ntoa(**(pptr++));
}
cout << ip_addr << endl;

cout << "Connecting to " << uri->Get_host() << "|" << ip_addr << "|:";
cout << port << "... ";
if ( connect( tcp_sock, (sockaddr*)&server, slen ) < 0 )
{
 cerr << "Unable to connect to server via TCP." << endl;
 close( tcp_sock );
 return 4;
}
cout << "connected." << endl;

// rest of code

+1  A: 

Take a look at this newsgroup post, with details and sample code for how to put a timeout on socket connections in Lunux. The basic idea is to use non-blocking sockets, and then wait for a connection.

Justin Grant
+3  A: 

Make the socket a non-blocking socket, and then use select() or poll() with a timeout value to check for writability. If the select() returns with a timeout you did not connect in time, and you can close the socket and deal with the connection failure. If it returns with a completion, everything is fine and you can proceed.

janm
+1  A: 

set non-blocking mode for your socket and use select to check whether connection established. here is the sample

elder_george
+1  A: 

Another way to do non-blocking without the pain of select() is to check GetLastError() for EWOULDBLOCK.

// set socket as nonblocking
unsigned long value = 1;
if (ioctlsocket(yourSocket, FIONBIO, &value) == SOCKET_ERROR)
 return SOCKET_ERROR;

// (call connect here)

// check if connect would block
if (GetLastError() == EWOULDBLOCK)
    return TIMEOUT;
Rantaak
That definitely seems the easiest, I will give it a try. Thank you.
Silmaril89
The problem with this is that any connection attempt that would block will fail. And if you're connecting to something on another machine, that will probably be every attempt.
janm
what must I #include to use ioctlsocket, FIONBIO, SOCKET_ERROR, GetLastError(), TIMEOUT
Silmaril89