程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 惱人的boost::asio::async_read_until

惱人的boost::asio::async_read_until

編輯:C++入門知識

最近為服務器添加XMLSocket與Flash進行通信, 這種協議其實是一種以\0結尾的字符串協議, 為了讓asio兼容此協議, 我從文檔找到了async_read_until異步讀取系列, 這個函數的原理時, 給定一個streambuf, 和一個分隔符, asio碰到分隔符時返回, 你可以從streambuf中讀取需要的數據. 看似很簡單, 我很快寫好一個demo與Flash進行通信, 結果發現在一個echo邏輯速度很快時, 服務器居然亂包了, 網上查了下, 官方原文是這樣的:

”After a successful async_read_until operation, the streambuf may contain additional data beyond the delimiter. An application will typically leave that data in the streambuf for a subsequent async_read_until operation to examine.”

意思是, streambuf中並不一定是到分隔符前的所有數據, 多余的數據可能一樣會在streambuf中. 也就是說, 還需要自己再次處理一遍數據...

動手呗, async_read_until看似就是一個廢柴, 底層已經費了很多CPU在逐字符與分隔符的匹配上, 拋上來的數據居然還是半成品.

代碼如下, 測試通過, 但是實在很費解為啥非要再做一次..

          boost::asio::streambuf* SB = SBP.get();

            // 訪問緩沖
            const char* Buffs = boost::asio::buffer_cast<const char*>( SB->data() );

            uint32 DataSize = 0;
            for ( uint32 i = 0; i < SB->size(); ++i )
            {
                const char DChar = Buffs[i];

                // 這裡需要自己判斷字符串內容, read_until的文檔裡這麼說的
                if ( DChar == '\0' )
                {
                    DataSize = i;
                    break;
                }
            }

            if ( DataSize > 0 )
            {
                // 取成字符串
                std::string FullText( Buffs, DataSize );
               
                // 消費
                SB->consume( DataSize );               

                mWorkService->post(
                    boost::bind(&AsioSession::NotifyReadString,
                    shared_from_this(),
                    FullText )
                    );

            } www.2cto.com
  另外, 為了保證輸入性安全, 可以在streambuf構造時加一個最大一個讀取量, 超過此量會返回報錯, 避免了緩沖區被撐爆的危險

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved