<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    關于IOCP,某些地方就是不讓人徹底舒服(WSASend重疊post數據)

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    開門見山,直接就事論事。

     

    假如有這么一個基于IOCP模型的Server,這個Server提供的所有服務中有這么一種服務……文件下載,我們再假設Server端存有一個20G的文件,客戶端這時發送一個請求到服務端來,客戶端要求下載這個20G的文件,由此可能引發一系列讓人頭疼的問題(不談TransmitFile,我們談WSASend)

     

    先給出一段偽代碼,這段代碼肯定是有問題的,如下:

    [html] view plaincopy
    1. //在某個線程里,我們開始向某個客戶端瘋狂發送這20G的文件了  
    2. while(true)  
    3. {  
    4.     char *data=new char[PER_SEND_DATA_LEN];  
    5.   
    6.     ::ReadFile(...,data,PER_SEND_DATA_LEN,&len,...);  
    7.   
    8.     io_data.wsabuf.buf=data;  
    9.     io_data.wsabuf.len=len;  
    10.     ::WSASend(...,&io_data.wsabuf,...);  
    11.   
    12.     delete []data;  
    13.       
    14.     if(len<PER_SEND_DATA_LEN) break;  
    15. }  

    這樣無節操的發送基本上會得到一個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中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全