簡體   English   中英

如何在循環中組合RECV和getMessage(C,WINAPI)

[英]How to combine RECV and getMessage in loop (C, WINAPI)

您如何用C編寫代碼?

所需的流為:

Create socket
Create window
loop: Wait until data can be read from socket or message are added to the queue
if data then
  do stuff with data
  goto loop
else if message then
  do stuff with message
  goto loop

我已經試過這段代碼:

MSG msg;
DWORD last=msg.time;
short bRet;
char command[20];
int n=0;
while((
       (n = recv(sock, command, sizeof command - 1, 0)) >= 0
       )||(
           (bRet = GetMessage( &msg, 0, 0, 0 )) != 0
           //I can't use peek message because it will have the same issue than non-blocking socket
           )){
    //here we check time of message if it is equal to last we know that is socket
}

我知道線程存在,但是我想避免使用線程。 如果這是唯一的方法,我將使用線程。

編輯:使用無阻塞套接字不是解決方案,因為如果沒有可用數據並且隊列中沒有消息,那么我的程序將退出。

通過WSAAsyncSelect()在異步(非非阻塞)模式下使用套接字:

WSAAsyncSelect函數請求套接字的網絡事件的基於Windows消息的通知。

套接字將向套接字指定的HWND通知套接字活動,例如可用數據。

然后,該應用程序可以運行標准消息循環,在套接字消息從隊列到達時對其進行處理。

#define WM_SOCKET_MSG (WM_APP + 1)

WSAAsyncSelect(sock, hwnd, WM_SOCKET_MSG, FD_READ | FD_WRITE | FD_CLOSE);

MSG msg;
char command[20];
int n;

while (GetMessage(&msg, 0, 0, 0)) {
        switch (msg.message) {
            case WM_SOCKET_MSG:
            {
                int event = WSAGETSELECTEVENT(msg.lParam);
                int error = WSAGETSELECTERROR(msg.lParam);
                if (error != 0) {
                    // process socket error as needed ...
                    break;
                }

                switch(event) {
                    case FD_READ:
                        n = recv(sock, command, sizeof command - 1, 0);
                        if (n > 0) {
                            // process data as needed ...
                        } else {
                            // process read error as needed ... 
                        }
                        break;
                    }

                    // process other socket events as needed ...
                }

                break;
            }

            // process other messages as needed ... 
        }
}

我肯定會為網絡recv()和所有相關的協議檢查/解析使用單獨的線程,因此將其與消息處理循環隔離。 這樣的線程將是合理可移植的。 該線程將生成“命令”結構實例(malloc),並將其激發到extern處理函數中。 在Windows上,該處理程序會將結構地址加載到WM_APP消息的lParam / hParam中,並將其發送到GetMessage()線程,在該處以通常的方式接收該地址,將其分配給處理程序,提取,執行然后提取結構釋放。

這樣的設計可能被視為過於復雜(並且使用了可怕的線程),但是與將所有內容塞入執行所有功能的異步消息循環中相比,測試,調試,擴展和增強功能要容易得多。 有時,額外的線程確實更容易:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM