DLL内的非阻塞套接字(无窗口)

时间:2009-11-24 14:05:04

标签: c++ windows dll sockets winsock

我有一个通过单个套接字连接到服务器的DLL。 我面临以下问题:如果服务器的IP地址& port为false或服务器已关闭,使用此DLL的应用程序冻结到半分钟。 我的想法是使用非阻塞套接字来避免这个问题,通过显示一个指示连接进度的窗口,并允许取消此过程。 但是我怎么能使用WSAAsyncSelect函数,因为我没有窗口处理程序?

7 个答案:

答案 0 :(得分:3)

如果要使用WSAAsyncSelect类型套接字,那么您的Dll将需要创建至少一个消息窗口来处理套接字事件。由于窗口永远不可见,因此它的WindowProc只包含您自定义消息的处理程序(WM_USER + 1),可能是您传递给WSAAsyncSelect的 - 其他所有内容都直接转到DefWindowProc。

您将不得不在连接上创建无模式进度窗口以显示您的连接UI。

答案 1 :(得分:2)

在我看来,您的根本问题是IO操作阻止了您的UI线程。我会尝试将连接移动到一个单独的线程,因为它不应该阻止UI,而是与它并行运行。无论如何,将IO操作与UI线程分开是一个好主意。您可以使用信号量等常规机制在两个线程之间进行通信。

如果可以的话,看看提升线程,它们很容易使用。

答案 2 :(得分:1)

我建议使用适当的库,例如boost::asio,它也是跨平台并提供异步连接处理功能

答案 3 :(得分:0)

使用非阻塞套接字的另一种方法是使用select() function

您可以通过检查套接字是否可写来确定连接的完成情况,
您还可以在select上指定超时。

答案 4 :(得分:0)

我同意使用非阻塞套接字,然后选择()是进入C的方法。这是一些基本的示例代码,在Windows上执行非阻塞连接,超时15秒。

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 */
}

答案 5 :(得分:0)

使用WSAAsyncSelect不是Winsock中非阻塞套接字的唯一选择。它实际上是旧的Winsock 1.1 / Win16做异步套接字的方式。

Winsock 2 + / Win32方式是使用重叠I / O.有关带套接字的重叠I / O的说明,请参阅this article

答案 6 :(得分:0)

HWND_MESSAGE作为父窗口传递给CreateWindow。这将创建一个没有窗口的消息队列。当然,您仍然需要一个WndProc,因为这是您处理消息的地方。