1

我是 win32 api 编程新手,我正在使用 win32 api 和 gloox xmpp 库为 windows 平台编写 xmpp 客户端。gloox 有自己的事件循环,而 windows GUI 也有消息循环。我不太清楚如何一起使用这两个循环。

来自 gloox 文档:

阻塞与非阻塞连接对于某些类型的机器人,阻塞连接(默认行为)是理想的。机器人所做的只是对来自服务器的事件做出反应。然而,对于最终用户客户端或任何带有 GUI 的东西来说,这远非完美。

在这些情况下,可以使用非阻塞连接。如果调用 ClientBase::connect( false ),则函数在连接建立后立即返回。然后程序员有责任开始从套接字接收数据。

最简单的方法是定期调用 ClientBase::recv() 并使用所需的超时(以微秒为单位)作为参数。默认值 -1 表示调用阻塞,直到收到任何数据,然后自动解析。

窗口消息循环:

   while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;

窗口过程:

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    TCHAR str[100];
    StringCbPrintf(str, _countof(str), TEXT("Message ID:%-6x:%s"), msg, GetStringMessage(msg));
    OutputDebugString(str);
    HDC hdc;
    PAINTSTRUCT ps;
    RECT rect;
    switch (msg)
    {
    case  WM_CREATE:
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        GetClientRect(hWnd, &rect);
        DrawText(hdc, TEXT("DRAW TEXT ON CLIENT AREA"), -1, &rect, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
        EndPaint(hWnd, &ps);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    default:
        break;
    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
}

gloox 阻塞连接

  JID jid( "jid@server/resource" );
  Client* client = new Client( jid, "password" );
  client->registerConnectionListener( this );
  client->registerPresenceHandler( this );
  client->connect();// here will enter event loop

gloox 非阻塞连接

Client* client = new Client( ... );
ConnectionTCPClient* conn = new ConnectionTCPClient( client, client->logInstance(), server, port );
client->setConnectionImpl( conn );
client->connect( false );
int sock = conn->socket();
[...]

我不太清楚我该怎么做

以所需超时(以微秒为单位)作为参数定期调用 ClientBase::recv()

带计时器?还是多线程编程?还是有更好的解决方案?

任何建议表示赞赏

谢谢

4

1 回答 1

0

The best IO strategy for that is overlapped IO. Unfortunately, the method is windows only, not supported by the cross-platform library you’ve picked.

You can use SetTimer() API, and periodically call recv() method of the library with zero timeout, in WM_TIMER handler. This will introduce extra latency (your PC receives a message but it has to wait for the next timer event to handle it), or if you’ll use small intervals like 20 ms, will consume battery on laptops or tablets.

You can use blocking API with a separate thread. More efficient performance-wise, but harder to implement, you’ll have to marshal messages and other events to the GUI thread. WM_USER+n custom windows messages is usually the best way to do that, BTW.

于 2019-06-01T10:48:42.333 回答