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

Posted

技术标签:

【中文标题】DLL 中的非阻塞套接字(无窗口)【英文标题】:Non blocking socket from within a DLL (no window) 【发布时间】:2009-11-24 14:05:04 【问题描述】:

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

【问题讨论】:

【参考方案1】:

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

无论如何,您都必须在连接时创建一个无模式的进度窗口以显示您的连接 UI。

【讨论】:

【参考方案2】:

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

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

【讨论】:

【参考方案3】:

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

【讨论】:

【参考方案4】:

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

可以通过检查socket是否可写来判断连接是否完成, 您还可以在select 上指定超时。

【讨论】:

【参考方案5】:

我同意使用非阻塞套接字,然后 select() 是在 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 */

【讨论】:

【参考方案6】:

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

Winsock 2+/Win32 的方式是使用重叠 I/O。请参阅this article 以了解与套接字重叠 I/O 的说明。

【讨论】:

【参考方案7】:

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

【讨论】:

以上是关于DLL 中的非阻塞套接字(无窗口)的主要内容,如果未能解决你的问题,请参考以下文章

没有 ConnectEx 的 Windows 上的非阻塞套接字连接

使用带有选择器的非阻塞模式下的 Java NIO 和 Unix 域套接字

在python中解析(流式传输)XML的非阻塞方法

使用 OTP 原则的非阻塞 TCP 服务器

设置非阻塞的套接字Socket

C++:如何测量非阻塞套接字的实际上传速率