關于IOCP,某些地方就是不讓人徹底舒服(WSASend重疊post數據)
開門見山,直接就事論事。
假如有這么一個基于IOCP模型的Server,這個Server提供的所有服務中有這么一種服務……文件下載,我們再假設Server端存有一個20G的文件,客戶端這時發送一個請求到服務端來,客戶端要求下載這個20G的文件,由此可能引發一系列讓人頭疼的問題(不談TransmitFile,我們談WSASend)
先給出一段偽代碼,這段代碼肯定是有問題的,如下:
[html] view plaincopy- //在某個線程里,我們開始向某個客戶端瘋狂發送這20G的文件了
- while(true)
- {
- char *data=new char[PER_SEND_DATA_LEN];
- ::ReadFile(...,data,PER_SEND_DATA_LEN,&len,...);
- io_data.wsabuf.buf=data;
- io_data.wsabuf.len=len;
- ::WSASend(...,&io_data.wsabuf,...);
- delete []data;
- if(len<PER_SEND_DATA_LEN) break;
- }
這樣無節操的發送基本上會得到一個WSAENOBUFS(緩沖區不足)錯誤,這個不是什么大問題,不會影響到IOCP底層模塊的設計,值得注意的是下面一個問題——數據發送不完全
接著上面的例子繼續思考下去。
假如其中一個WSASend投遞長度為PER_SEND_DATA_LEN的數據,而GetQueuedCompletionStatus(...,&BytesTransferred,...)返回結果卻表明這次發送沒有進行完全,BytesTransferred<PER_SEND_DATA_LEN,而后續的WSASend函數正源源不斷地投遞新的請求,即使我們在Get函數返回后,再次投遞WSASend請求補發剩余數據,也無法保證這樣的補發可以趕在其他WSASend的前面。
如果以上推測成立的話,那么數據將不可避免的出現亂序。
當然,這只是一種擔心,實際上到目前為止,本人還沒有遇到過這種情況,個人認為:這種情況應該不會發生,一定是哪些地方還沒有搞透徹,否則重疊的意義何在?不過,網上擔心這種情況的人也不少,以下是提出這些問題的鏈接(不保證都是原創):
http://blog.csdn.net/skiing_886/article/details/8044186
http://bbs.eyuyan.com/read.php?tid=306324
上面兩個鏈接中,其中一個是篇博客,博客中明言WSASend帶重疊結構投遞請求時,不會出現數據發送不完全的情況,本人比較容易相信別人,于是我就信了。就算那篇博客說錯了,本人也還是覺得數據亂序的情況不會發生。
下面,本人想就這個問題,結合IOCP的完成隊列說一些自己的猜想(完全是猜想,假設WSASend所投遞的數據有可能發送不完全)。
首先,IOCP維護著一個的隊列,這個隊列沒有好妖魔化的,就是一個先進先出的數據結構,效率很高就是了。問題是,是不是我們每次調用WSASend都將導致一次入列,而每次GetQueuedCompletionStatus函數返回都會導致一次出列呢?
結合上面的那個下載文件的例子,細細一想,如果每次GetQueuedCompletionStatus返回都要出列一次數據包的話,那一旦出現數據發送不完全的情況,即使我們再次調用WSASend補發,那也只能將數據附加到完成隊列的頭部,亂序是必然的。
但是,換個思維,這種問題連我都能想到,微軟那么多高智商人才難道都是吃干飯的嗎?
所以,我認為,當數據發送不完全的時候,GetQueuedCompletionStatus應該是不會出列數據的,而可能是占著茅坑不拉屎,等待WSASend再次補發未完成的數據發送,而這個WSASend肯定不會導致數據數據重新入列,而只是給一個繼續發送的信號。
如果是我的,我肯定會這樣設計,否則,那就只能采取保險的做法,WSASend不重疊投遞,一次投遞之后需要等待Get函數返回再決定是要投遞一個補發的WSASend請求還是投遞下一個完整數據包的WSASend請求。這種做法雖然保險,但這突出了IOCP的巨大缺陷,正如我前面所說的,重疊的意義何在?WSASend還有必要帶著個OVERLLAPED結構嗎?
所以,我認為,這種情況的數據亂序不可能發生,不用擔心,嗯,不擔心……
說到最后,再順便提一下STL。STL的出列操作是Pop,它是不帶任何返回值的出列,要想知道出列了什么數據必須在Pop之前調用front方法。有人強烈鄙視這種設計,認為這種設計極其別扭。要知道,STL的設計者必然是高手,設計成這樣自然有理由,隊列這種東西,要想通用的話,最好還是要把‘看’和‘取’分開,STL的設計是綜合考慮的結果。
RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成