2014-12-03 75 views
0

下面的代碼肯定能行,但並不快如我所料。read_some()的作品,但速度很慢,閱讀()不

我希望我的程序在很好的速度讀取數據。還有另一個商業應用程序連接到相同的服務器&以驚人的速度獲取數據。服務器端不是問題。

class A 
{ 
    //... 

    boost::asio::ip::tcp::socket* myPort; 
} 

void A::OpenPort() 
{ 
    if(myPort) 
    { 
     if(myPort->is_open()) 
     { 
      return; 
     } 
    } 

    // make the connection 
    Connect(); 

    if(! myPort->is_open()) 
    { 
     return; 
    } 

    // set the protocol 
    static string init("INIT\r\n"); 
    myPort->write_some(boost::asio::buffer(init.c_str(), init.length())); 
} 

void A::Read() 
{ 
    static string prev_msg = ""; 

    try 
    { 
     OpenPort(); 

     while(true) 
     {     
      boost::system::error_code error; 

       boost::asio::streambuf streamBuf; 
       boost::asio::streambuf::mutable_buffers_type mutableBuffer = streamBuf.prepare(614400); 
       size_t bytes_transferred = myPort->read_some(boost::asio::buffer(mutableBuffer), error); 

       if (error) 
       { 
        if (error != boost::asio::error::eof) 
        { 
         throw boost::system::system_error(error); // Some other error. 
        } 
       } 

       // add to any previous message we might not have processed 
       streamBuf.commit(bytes_transferred); 
       istreambuf_iterator<char> sbit(&streamBuf); 
       istreambuf_iterator<char> end; 
       string s(sbit, end); 
       prev_msg.append(s); 

       string delimiter1 = ",\r\n"; 

       size_t pos1 = 0; 

       string response; 

       while ((pos1 = prev_msg.find(delimiter1)) != std::string::npos) 
       { 
        response = prev_msg.substr(0, pos1); 

        //SOME PROCESSING ON THE RESPONSE RECEIVED 
       } 
     } 
    } 
    catch (boost::system::system_error const& ex) 
    { 
     cout<<ex.what(); 
    } 
} 

很明顯,問題是read_some(),程序在一次讀取操作中讀不到完整的數據,有時它接收到614000字節,有時甚至更少。 我不想強制任何服務器發送緩衝區大小的限制,程序應該一次讀取所有數據。

因此,我決定用剛讀()。但是,現在程序停留在read(); read()調用不會返回。

boost::asio::streambuf streamBuf; 
size_t bytes_transferred = read(*myPort, streamBuf, error); 

if (error) 
{ 
    if (error != boost::asio::error::eof) 
    { 
     throw boost::system::system_error(error); // Some other error. 
    } 
} 

我必須處理請求下一個數據之前接收到的數據,因此,我不能使用async_read()。

+0

更換你可能要考慮重新設計程序中使用異步函數來代替。每個異步讀取回調都會收到一部分消息,當收到完整的消息時,將其放入隊列中並讓主線程處理它。 – 2014-12-03 09:08:19

+0

不是因爲你的線程睡了10ms'boost :: this_thread :: sleep(boost :: posix_time :: milliseconds(10));'? – doc 2014-12-03 09:09:25

+0

@doc,不!!!!!!! – user1 2014-12-03 09:11:48

回答

1

有幾件事情:

  • 使用TCP你永遠不能肯定,你會一次過獲得的一切。
  • 因爲你正在閱讀到一個分隔符,read_until()可能是你追求的。
  • 確保您有O_NDELAY打開插座,否則你會爲200ms添加到您的寫操作。通過在您的代碼中適當地調用myPort->set_option(tcp::no_delay(true))來完成此操作。
  • 睡眠不是一個好主意。設計你的代碼,使其不是必需的。
  • 如果套接字已關閉,則您的代碼似乎進入無限循環。
  • 您在不檢查返回值的情況下致電write_some()。您應該撥打write()以確保您的所有數據都已寫入。
  • 如果你有很多線程,你可能會從重新設計你的代碼變得異步。
+0

不要擔心無盡的循環。我在這裏添加的並不是我正在處理的完整解決方案。睡眠()再次不是問題。我編輯了我的帖子。 – user1 2014-12-03 09:15:23

+1

@ user3924882好的,當然。其他評論立場! – janm 2014-12-03 09:16:26

+2

@ user3924882如果您已經熟悉代碼以「改善」事情,那麼它就是潛在設計問題的標誌。這個問題並不明顯是'read_some()'。我懷疑反思你的代碼會有所幫助。 – janm 2014-12-03 09:21:59

1

不要在每次循環分配一個新的緩衝區,這樣做只有一個外循環時間。

while(true) 
    {     
     boost::system::error_code error; 

      boost::asio::streambuf streamBuf; 
      boost::asio::streambuf::mutable_buffers_type mutableBuffer = streamBuf.prepare(614400); 
      size_t bytes_transferred = myPort->read_some(boost::asio::buffer(mutableBuffer), error); 
... 

boost::system::error_code error; 
    boost::asio::streambuf streamBuf; 
    boost::asio::streambuf::mutable_buffers_type mutableBuffer = streamBuf.prepare(614400); 
    while(true) 
    {     
      size_t bytes_transferred = myPort->read_some(boost::asio::buffer(mutableBuffer), error); 
...