概述
MSDN對CAsyncSocket的解釋很容易讓你理解為:只有OnSend被觸發時
你Send才有意義,你才應該Send,同樣只有OnRecieve被觸發時你才
應該Recieve。很不幸,你錯了:
你會發現,連線建立的同時,OnSend就第一次被觸發了,嗯,這很好,
但你現在還不想Send,你讓OnSend返回,乾點其他的事情,等待下一
次OnSend試試看?實際上,你再也等不到OnSend被觸發了。因為,除
了第一次以外,OnSend的任何一次觸發,都源於你調用了Send,但碰
到了WSAEWOULDBLOCK或只完成了部分傳送!
所以,使用CAsyncSocket時,針對傳送的流程邏輯應該是:你需兩個
成員變數,一個傳送任務表,一個記錄傳送進度。你可以,也應該,
在任何你需要的時候,主動調用Send來傳送數據,同時更新任務表和
傳送進度。而OnSend,則是你的負責擦屁股工作的助手,它被觸發時
要幹的事情就是根據任務表和傳送進度調用Send繼續發,若此次傳送
沒能將任務表全部傳送完成,根據傳送結果更新傳送進度;若任務表
已全部傳送完畢,則清空任務表及傳送進度。
相關
使用CAsyncSocket的接收流程邏輯是不同的:你永遠不需要主動調用
Recieve,你只應該在OnRecieve中等待。由於你不可能知道將要抵達
的數據類型及次序,所以你需要一個成員變數來存儲已收到但尚未處
理的數據。每次OnRecieve被觸發,你只需要被動調用一次Recieve來
接受固定長度的數據,並添加到你的已收數據表後。然後你需要掃描
已收數據表,若其中已包含一條或數條完整的可解析的業務數據包,
截取出來,調用主執行緒的處理函式來處理或作為訊息參數傳送給主線
程。而已收數據表中剩下的數據,將等待下次OnRecieve中被再次組合
、掃描並處理。
在長連線套用中,連線可能因為各種原因中斷,所以你需要自動重連。
你需要根據CAsyncSocket的成員變數m_hSocket來判斷當前連線狀態:
if(m_hSocket==INVALID_SOCKET)
當然,很奇怪的是,即使連線已經中斷,OnClose也已經被觸發,你
還是需要在OnClose中調用Close,否則m_hSocket並不會被自動賦值
為INVALID_SOCKET。
在很多長連線套用中,除建立連線以外,還需要先Login,然後才能
進行業務處理,連線並Login是一個步驟依賴性過程,用異步方式處
理反而會很麻煩,而CAsyncSocket是支持切換為同步模式的,你應該
掌握在適當的時候切換同異步模式的方法:
DWORD dw;
//切換為同步模式
dw=0;
IOCtl(FIONBIO,&dw);
...
//切換回異步模式
dw=1;
IOCtl(FIONBIO,&dw);