Connect with timeout for blocking sockets
Posted by AnwarJun 14
If you ever programmed networking applications then you should know that it is impossible to control the timeout for blocking sockets on calling connect() function. This timeout is controlled by the operating system and may last up to 45 seconds when you want to connect to a non-existing host. Since blocking sockets are very attractive due to their simplicity in usage comparing to non-blocking (asynchronous) sockets, such a limitation disappoints many developers. You can change the value of timeout globally for the system, but I would like to warn you to avoid making any changes of the operating systems, as these changes will affect ALL networking applications running on your computer. In most cases, such a behavior is not desired.
In order to solve this problem you can use the following trick.
You can temporarily change the mode of the socket from blocking to non-blocking. Then connect to the target host using connect() function. If the return value is WSAEWOULDBLOCK, then just wait for the specified time using select() function checking the socket for writability.
Here is the code of the connectex() function, which you can use instead of the regular connect().
//************************************ // Method: connectex // Description: Connect with timeout for blocking sockets // Parameter: SOCKET s - socket handle // Parameter: const struct sockaddr * name - socket address structure // Parameter: int namelen - length of the socket address structure // Parameter: long timeout - timeout value in milliseconds // Returns: int : 0 - success, SOCKET_ERROR - error //************************************ int connectex(SOCKET s, const struct sockaddr *name, int namelen, long timeout) { // As connect() but with timeout setting. int rc = 0; ULONG ulB; struct timeval Time; fd_set FdSet; ulB = TRUE; // Set socket to non-blocking mode ioctlsocket(s, FIONBIO, &ulB); if (connect(s, name, sizeof(SOCKADDR)) == SOCKET_ERROR) { if (WSAGetLastError() == WSAEWOULDBLOCK) { // now wait for the specified time FD_ZERO(&FdSet); FD_SET(s, &FdSet); Time.tv_sec = timeout / 1000L; Time.tv_usec = (timeout % 1000) * 1000; rc = select(0, NULL, &FdSet, NULL, &Time); } } ulB = FALSE; // Restore socket to blocking mode ioctlsocket(s, FIONBIO, &ulB); return (rc > 0) ? 0 : SOCKET_ERROR; }
This code is not mine. I personally, modified it for my own needs.
2 comments
Pingback by Anwar Shafiev » Connect Ñ Ñ‚Ð°Ð¹Ð¼Ð°ÑƒÑ‚Ð¾Ð¼ Ð´Ð»Ñ Ð±Ð»Ð¾ÐºÐ¸Ñ€ÑƒÑŽÑ‰Ð¸Ñ… Ñокетов on June 14, 2007 at 12:49 pm
[…] уÑтановить Ñоединение Ñ Ð½ÐµÑущеÑтвующим хоÑтом. СтатьÑ, Ð¾Ð¿ÑƒÐ±Ð»Ð¸ÐºÐ¾Ð²Ð°Ð½Ð½Ð°Ñ Ð½Ð° английÑком Ñзыке, опиÑывает трюк, […]
Comment by Phuoc on July 1, 2014 at 11:09 am
Thank you for your example. It works well