views:

252

answers:

9

Hi all,

I have a DLL wich connects to a server through a single socket. I am facing the following problem : If server's IP address & port are false or server is down, the application using this DLL freezes until half a minute. My idea is to use non-blocking sockets to avoid that problem, by showing a window indicating connection progress, and also allowing to cancel this process. But how could I use WSAAsyncSelect function as I have no window handler ?

+2  A: 

It seems to me that your root problem is that IO operations are blocking your UI thread. I would try to move the connection to a separate thread as that should not block the UI, but run in parallel with it. It's a good idea to keep IO operations separate from the UI thread anyway. You can communicate between the two threads using the normal mechanisms such as semaphores.

Take a look at boost threads if you can, they're quite easy to use.

laura
+1  A: 

I suggest using an appropriate library, such as boost::asio which is also crossplatform and offers async connection handling capabilities

catwalk
+2  A: 

If you want to use WSAAsyncSelect type sockets then your Dll will need to create at least one message window to handle socket events. As the window will never be visible, its WindowProc would consist only of a handler for your custom message (WM_USER+1) probably that you passed to WSAAsyncSelect - everything else goes straight to DefWindowProc.

You are going to have to create a modeless progress window on connect anyway to show your connecting UI.

Chris Becke
A: 

Another approach with a nonblocking socket is to use the select() function.

You can determine the completion of the connection by checking to see if the socket is writeable,
and you can also specify a timeout on the select.

Nick D
A: 

I would agree that using a non-blocking socket, and then select() is the way to go in C. Here's some basic sample code that does a non-blocking connect on Windows with a 15 second timeout.

int                     s;
long                    on = 1L;
int                     socketsFound;
struct timeval          timeout;
fd_set                  wfds;
struct addrinfo        *addrInfo,


s = socket(addrInfo->ai_family, addrInfo->ai_socktype, addrInfo->ai_protocol);
if (s < 0)
{
    /* Error */
    return ;
}

if (ioctlsocket(s, FIONBIO, (u_long *)on))
{
    /* Error */
    return ;
}

if (connect(s, addrInfo->ai_addr, addrInfo->ai_addrlen) < 0)
{       
    if (WSAGetLastError()!= WSAEWOULDBLOCK)
    {
        /* Connection failed */
        return;
    }
}

/* 15 second timeout */
timeout.tv_sec  = (long)15;
timeout.tv_usec = 0;

FD_ZERO(&wfds);
FD_SET(s, &wfds);

socketsFound = select((int)s+1, NULL, &wfds, NULL, &timeout);
if (socketsFound > 0 && FD_ISSET( s, &wfds ))
{
    /* Connected */
}
Steve Wranovsky
A: 

Using WSAAsyncSelect isn't your only choice for non-blocking sockets in Winsock. It's actually the old Winsock 1.1/Win16 way of doing asynchronous sockets.

The Winsock 2+/Win32 way is to used overlapped I/O. See this article for a description of overlapped I/O with sockets.

shf301
A: 

Hi all,

Thanks for your answers, but as I have to catch user's action on progress indicator UI I provide (in case of connection cancellation), I think WSAAsyncSelect is the best choice as "WSAAsyncSelect maps socket notifications to Windows messages and is the best model for a single threaded GUI application". So, by using this function, my hope is to catch window messages (such as cancel button clicked) and socket connection event. My problem is now to understand how to do that, as I am a windows programming newbie :-(

alain13
A: 

Solved : I finally decided to use select() and set a shorter timeout than TCP's one. Thanks to all !

alain13
A: 

Pass HWND_MESSAGE as the parent window to CreateWindow. This will create a message queue without a window. You will still need a WndProc, of course, because that's where you will process the messages.

MSalters