Adding a Timeout to an RWSocket::connect() Call

Article ID: 1109
Last updated: 01 Feb, 2008
Article ID: 1109
Last updated: 01 Feb, 2008
Revision: 1
Views: 5767
Posted: 21 Apr, 1999
by Dean J.
Updated: 01 Feb, 2008
by Dean J.
Problem


If I attempt to connect to a server which has shutdown or is not responding, for whatever reason, the connect call can take anywhere from 40 seconds to a few minutes to return. Is there a way to set a timeout on the connect() call so that it will return in less time?


Cause


The connect() call in RWSocket is a wrapper for the underlying socket API connect() call. Since there isn't a way to provide a timeout to this underlying API call, there isn't a way to directly set a timeout on a RWSocket::connect() call. However, there is an indirect solution, see below...


Action


Since we cannot directly add a timeout to the RWSocket::connect() itself, we will have to instead implement the timeout using the select mechanism (which provides a timeout), and a non-blocking connect() call. The following code illustrates how this can be done:

#include  #include  #include  #include  #include  #include   int main(int argc, char* argv[]) {   try    {     int tmout = 5; // seconds before time out occurs     RWCString url(nowhere.roguewave.com:2000);     RWInetAddr addr(url);     RWSockType sock_type(AF_INET, AF_INET);     RWSocket sock(sock_type);                            // 1      SET_NON_BLOCKING(sock)                               // 2      sock.connect(addr);                                  // 3      RWTValOrderedVector con, ret;
con.append(RWSocketAttribute(sock,
RWSocketAttribute::sock_attr_canwrite)); // 4
ret = rwSocketSelect(con, tmout); // 5

if (!ret.entries()) // 6
{
/* a timeout occurred, handle appropriately */
sock.close(); // 7
}
else
{
if (ret[0].attribute() &
RWSocketAttribute::sock_attr_canwrite) // 8
{
if (sock.getsockopt(SO_ERROR) || // 9
(ret[0].attribute() &
RWSocketAttribute::sock_attr_canread)) // 10
{
/* an error occurred, handle appropriately */
}
else // 11
{
/* Success! the socket is ready for use */
}
}
}
SET_BLOCKING(sock) // 12
}
catch (RWxmsg& msg)
{
cout << Exception: << msg.why() << endl;
return 1;
}
return 0;
}


/* Comments:

1. Create and initialize the socket.
2. Change the state of the socket to non-blocking, so
that the connect call can return immediately.
3. Connect to the target machine, this will return
immediately.
4. Create an array of attibutes to select upon. In this
case, we want to wait for the socket to be writable.
5. Perform the select.
6. Check the return to see if any of the attributes
matched. If they didn't then the timeout was reached.
7. We don't want to waste CPU time trying to connect, so
close the socket.
8. Check if the write attribute is set.
9. Check if any errors occurred.
10. Check if the read attribute is set. If it is, the
socket is invalid.
11. The socket is connected properly and should be ready
for use.
12. Change the state of the socket back to blocking.
*/
This article was:   Helpful | Not helpful
Report an issue
Article ID: 1109
Last updated: 01 Feb, 2008
Revision: 1
Views: 5767
Posted: 21 Apr, 1999 by Dean J.
Updated: 01 Feb, 2008 by Dean J.

Others in this category