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