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

发布于 2024-08-12 03:24:59 字数 172 浏览 5 评论 0原文

我有一个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

一百个冬季 2024-08-19 03:24:59

如果您想使用 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.

柠北森屋 2024-08-19 03:24:59

在我看来,你的根本问题是 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.

泅人 2024-08-19 03:24:59

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

迷爱 2024-08-19 03:24:59

使用非阻塞套接字的另一种方法是使用 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.

为你拒绝所有暧昧 2024-08-19 03:24:59

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

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 */
}
薄荷→糖丶微凉 2024-08-19 03:24:59

使用 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.

别念他 2024-08-19 03:24:59

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文