繼承 Berkeley Sockets,新增:
WSAAsyncSelect 註冊網路事件,事件發生時送指定訊息至視窗程式。WSAAsyncGetXByY 系列,非阻塞查詢主機/服務資訊。BlockingHook 處理訊息迴圈,避免凍結 UI。WSAGetLastError/WSASetLastError 支援多執行緒。WSAStartup/WSACleanup 版本協商。int WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg, long lEvent);
| lEvent 旗標 | 觸發條件 |
|---|---|
| FD_READ | 套接字可讀 (資料到達) |
| FD_WRITE | 套接字可寫 (緩衝區可用) |
| FD_OOB | 帶外資料到達 |
| FD_ACCEPT | 新連線請求 |
| FD_CONNECT | 連線完成 (客戶端) |
| FD_CLOSE | 連線關閉 |
範例:WSAAsyncSelect(s, hWnd, WM_USER_SOCK, FD_READ | FD_WRITE); 註銷:lEvent = 0。
WORD wVer = MAKEWORD(1,1);
WSADATA wsaData;
if (WSAStartup(wVer, &wsaData) != 0) return;
if (LOBYTE(wsaData.wVersion)!=1 || HIBYTE(wsaData.wVersion)!=1) {
WSACleanup(); return;
}
多次呼叫 WSAStartup 需保證版本參數一致。
視窗程式中處理自訂訊息 UM_SOCK:
case UM_SOCK:
switch (WSAGETSELECTEVENT(lParam)) {
case FD_READ:
len = recv(wParam, buf, sizeof(buf), 0);
break;
case FD_WRITE:
while (send(wParam, buf, len, 0) != SOCKET_ERROR) ;
break;
}
break;
len = send(s, buf, len, 0);
if (len == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK) {
// 緩衝區滿,稍後重試或等待 FD_WRITE
}
BlockingHook 只抓取/派發視窗訊息。WSASetBlockingHook 安裝自訂鉤子 (不可呼叫其他 Winsock API,僅能呼叫 WSACancelBlockingCall 取消阻塞)。WSACancelBlockingCall 終結阻塞迴圈。