1 在windows CE5.0中不支援WSAAsyncSelect函數,這個函數調用後會自動將通訊端(可能是Socket的音譯)設定成為 非阻塞模式,並向winsock Dll 註冊一個或幾個感興趣的事件(FD_CLOSE...),並提供一個通知時使用的視窗控制代碼,當註冊的網路事件發生時,對應的視窗將收到一個基於訊息的通知,就可以寫處理代碼了。
替代函數可以使用select或者WSAEventSelect,其中WSAEventSelect和WSAAsyncSelect的最大區別是網路事件會被發送到一個事件物件控點,而不是發送到一個視窗。
這個WSAEventSelect要求2.0的winsock版本:Requirements
Version: Requires Windows Sockets 1.1 or later.
Header: Declared in Winsock2.h.
Library: Use Ws2_32.lib.
2 select函數可以用於阻塞和非阻塞IO中,也就是說調用了select後不會自動將通訊端設定成非阻塞模式,該是什麼模式就是什麼模式,其實也沒什麼,如果是阻塞模式,也不會阻塞在recv函數處,而是阻塞在select函數處,但select有逾時退出機制,使用timeval來確定等待的事件,退出後就可以幹別的事情了,幹完了回來繼續阻塞在select處。採用一個while(1)即可。
3 網路函數中,所以關係到收發資料的緩衝都屬於簡單的char類型,也就是說,這些函數沒有沒有“Unicode”版本,使用Unicode的時候需要把想發送的字串當成char*或者乾脆把它轉換成為char*發送:在利用字串長度函數告訴winsock API函數收發的資料有多少字元時,需要乘以2,因為---每個字元佔用字串數組的兩個位元組。此外也可以在將字串資料賦給Winsock API前,用WideCharToMultiByte把UNICODE轉換成ASCii碼。在我的windowCE程式中我採用後者,好處:網路傳輸的資料量少了二分之一。
由於沒有Uncode版本的winsock函數,於是當把_T("192.168.0.10")傳遞給connect函數,是可以編譯通過的,但是卻無法串連的上,呵呵,為了這個錯誤,費了好大氣力尋找。
4 先看一段節選自MSDN的關於WSAEnumNetworkEvents函數的解釋:
The socket's internal record of network events is copied to the structure referenced by lpNetworkEvents, after which the internal network events record is cleared. If the hEventObject parameter is not NULL, the indicated event object is also reset. The Windows Sockets provider guarantees that the operations of copying the network event record, clearing it and resetting any associated event object are automatic, such that the next occurrence of a nominated network event will cause the event object to become set. In the case of this function returning SOCKET_ERROR, the associated event object is not reset and the record of network events is not cleared.
這裡邊值得注意的是最後一句話。
5 if (networkEvents.lNetworkEvents & FD_CLOSE)
{
if (0 != networkEvents.iErrorCode[FD_CLOSE_BIT])
{
::PostMessage((HWND)lpParameter, WM_SERVER_MESSAGE, 0, 2);
}
else
{
::PostMessage((HWND)lpParameter, WM_SERVER_MESSAGE, 0, 1);
getpeername(g_Socks[index - WSA_WAIT_EVENT_0],(sockaddr*)&name,&namelen);
//closesocket(g_Socks[index - WSA_WAIT_EVENT_0]); //加上這句話會進入死迴圈
}
}
不知道為什麼使用closesocket總是出現問題,如果加上這一句會出現FD_CLOSE無法清除或者反覆由系統發出(搞不清是哪種情況,但傾向於後者)而導致死迴圈的問題。
6 while(1)
{
if( TRUE == g_bQuit )
break;
index = WSAWaitForMultipleEvents(g_NumOfEvents, g_Events, /
FALSE, WSA_INFINITE/*TIMEOUT_USECS*/, FALSE);
TRACE(_T("index:%d/tg_NumOfEvents:%d/n"), index, g_NumOfEvents);
此處如果用TIMEOUT_USECS會發生產生無限多個FD_ACCEPT的情況而導致死迴圈。這個沒搞清楚是怎麼回事
7 int res = recv(g_Socks[index - WSA_WAIT_EVENT_0], pbuf, BUF_SIZE, 0);
if (res > 0)
{
pbuf += res;
if (TCPIP_DATA_LENGTH == pbuf - buf) //此處的重大缺陷是如果接收到的資料一次或者累計(未恰好達到TCPIP_DATA_LENGTH)超過TCPIP_DATA_LENGTH,則永遠無法顯示
{
buf[TCPIP_DATA_LENGTH] = '/0';
g_csNet.Lock();
memcpy(g_buf, buf, sizeof(buf));
write by xiaoxiongli未完。。。