DLL 内的非阻塞套接字(无窗口)
我有一个 DLL,通过单个套接字连接到服务器。 我面临以下问题:如果服务器的IP地址&端口错误或服务器关闭,使用此 DLL 的应用程序会冻结直到半分钟。 我的想法是使用非阻塞套接字来避免该问题,通过显示一个指示连接进度的窗口,并允许取消此过程。 但是我如何使用 WSAAsyncSelect 函数,因为我没有窗口处理程序?
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 ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
如果您想使用 WSAAsyncSelect 类型套接字,那么您的 Dll 将需要创建至少一个消息窗口来处理套接字事件。由于窗口永远不可见,因此它的 WindowProc 将仅包含您的自定义消息 (WM_USER+1) 的处理程序(可能是您传递给 WSAAsyncSelect 的处理程序) - 其他所有内容都直接进入 DefWindowProc。
无论如何,您都必须在连接时创建一个无模式进度窗口来显示您的连接 UI。
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.
在我看来,你的根本问题是 IO 操作阻塞了你的 UI 线程。我会尝试将连接移至单独的线程,因为这不应阻塞 UI,而是与其并行运行。无论如何,将 IO 操作与 UI 线程分开是个好主意。您可以使用常规机制(例如信号量)在两个线程之间进行通信。
如果可以的话,看看 boost 线程,它们非常容易使用。
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.
我建议使用适当的库,例如 boost::asio< /a> 这也是跨平台的并提供异步连接处理功能
I suggest using an appropriate library, such as boost::asio which is also crossplatform and offers async connection handling capabilities
使用非阻塞套接字的另一种方法是使用 select( )函数。
您可以通过检查套接字是否可写来确定连接是否完成,
您还可以在
select
上指定超时。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
.我同意使用非阻塞套接字,然后 select() 是 C 语言中的方法。下面是一些基本示例代码,它在 Windows 上进行非阻塞连接,超时时间为 15 秒。
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.
使用 WSAAsyncSelect 并不是 Winsock 中非阻塞套接字的唯一选择。它实际上是旧的 Winsock 1.1/Win16 执行异步套接字的方法。
Winsock 2+/Win32 方式是使用重叠 I/O。有关套接字重叠 I/O 的说明,请参阅本文。
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.
将
HWND_MESSAGE
作为父窗口传递给CreateWindow
。这将创建一个没有窗口的消息队列。当然,您仍然需要一个 WndProc,因为您将在其中处理消息。Pass
HWND_MESSAGE
as the parent window toCreateWindow
. 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.