1

I am new to win32 api progamming, and I am tring writing a xmpp client for windows platform, using win32 api and gloox xmpp library. gloox has its own event loop, while windows GUI has message loop too. I am not very clear how to use these two loops together.

From the gloox document:

Blocking vs. Non-blocking Connections For some kind of bots a blocking connection (the default behaviour) is ideal. All the bot does is react to events coming from the server. However, for end user clients or anything with a GUI this is far from perfect.

In these cases non-blocking connections can be used. If ClientBase::connect( false ) is called, the function returnes immediately after the connection has been established. It is then the resposibility of the programmer to initiate receiving of data from the socket.

The easiest way is to call ClientBase::recv() periodically with the desired timeout (in microseconds) as parameter. The default value of -1 means the call blocks until any data was received, which is then parsed automatically.

Window message loop:

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

Window proc:

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 blocking connection

  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 non-blocking connection

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

I am not very clear how can I

call ClientBase::recv() periodically with the desired timeout (in microseconds) as parameter

With a timer ? or multi thread programming ? or there is a better solution ?

Any suggestions appreciated

Thank you

Community
  • 1
  • 1
zhuo.quan
  • 63
  • 7

1 Answers1

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.

Soonts
  • 20,079
  • 9
  • 57
  • 130