2013-07-27 26 views
1

同時編寫支持TCP和UDP的服務器與boost庫,我遇到了一個奇怪的問題:在服務器收到任何UDP消息後,調用std :: cin(或std :: getline)會崩潰,如果我嘗試將輸入到一個字符串。boost async_receive_from使std :: cin崩潰,緩衝區溢出

這隻會在收到至少一個UDP消息後纔會發生。我不知道這裏會發生什麼,因爲收到消息時我幾乎不做任何事情。我打破了重要的代碼了下來:

void AsynchronousServer::DoReceiveUDP() 
{ 
    m_udp_socket.async_receive_from(boost::asio::buffer(m_udp_receive_buffer, 
     m_udp_receive_buffer.size()), 
    udp::endpoint(), [this](boost::system::error_code error, std::size_t 
     bytes_transferred) 
    { 
    }); 
} 

的DoReceiveUDP()方法被調用權當服務器啓動並io_service.run前()。通常它會做更多的事情(例如再次調用自己),但出於測試目的,我評論了所有內容,以便它只會接收一次。 m_udp_receive_buffer是

std::array<char, 8196> 

,不用於其他任何地方的AsynchronousServer類的屬性。

在主線程,這是所有設置服務器後,我真的:

while(true) 
{ 
    std::string message; 
    std::getline(std::cin, message); //On this line the program crashes 
    //server.SendMessageTCP(1, message); 
} 

現在,就像我說的,崩潰的原因(調試消息說,緩衝區溢出)只能通過收到的消息後會發生UDP。我的服務器還通過async_read讀取TCP消息。儘管如此,這並不會引起錯誤。

我還測試了這一點,將getline-input存儲在一個常數大小的數組中,它工作正常。但我不能這麼做,因爲我不知道那時候的信息有多長,這意味着當我發送信息時,緩衝區裏充滿了大量無用的字符。此外,我不會真正感到安全無論如何發生這種奇怪的事情,寧願解決問題,而不是繞過它。

對於這裏可能出現的問題,你們有沒有一些想法?如果您需要更多代碼,只需詢問,但我認爲我已經發布了所有相關內容。 :)

編輯:我註釋了錯誤代碼和字節也轉移,但它是在「完整」版本。我沒有收到任何錯誤,傳輸的字節正好是消息的長度。

經過一些測試後,我至少可以多猜一猜。如果我希望通過cin輸入輸入,並且在此期間收到一條消息,問題似乎就會發生。

E.g.如果我這樣做:

while(true) 
{ 
    std::string message; 
    boost::this_thread::sleep(boost::posix_time::seconds(3)); 
    std::getline(std::cin, message); 
} 

和客戶端發送一個UDP消息在這三秒內線程睡眠,一切都很好。如果三秒鐘過去,那麼接收到該消息,它就像以前一樣崩潰。

但是,有一個非常奇怪的行爲:在這三秒內發送UDP消息之後,程序不會再崩潰 - 即使我等待下一條消息,直到線程再次到達getline。我不知道爲什麼會發生這種情況......

+0

你是不是檢查在async_receive_from處理程序中的錯誤參數。同樣,接收多少個字節? –

+0

是的,我評論說,但它是在'完整'版本。我沒有得到任何error_code。收到的字節正好是消息的長度。 – user2623674

+0

您可能有對象生存期問題,請發佈'AsynchronousServer'的定義。 –

回答

0

好吧,我找到了解決這個問題的方案。我仍然不知道爲什麼會發生這種情況,如果這真的是一個解決方案,或者稍後我會遇到其他問題。

另外,我不知道,爲什麼這個解決方案的作品。:d

無論如何,它的工作原理如果緩衝區不是一個成員函數但ReceiveUDP的每一個電話重新創建:

void AsynchronousServer::DoReceiveUDP() 
{ 
    std::shared_ptr<std::array<char, 8192>> udp_receive_buffer; 

    m_udp_socket.async_receive_from(boost::asio::buffer(*udp_receive_buffer, udp_receive_buffer->size()), 
     udp::endpoint(), boost::bind<void>([this](boost::system::error_code error, std::size_t bytes_transferred, 
    std::shared_ptr<std::array<char, 8192>> udp_receive_buffer) 
    { 
    }, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, udp_receive_buffer)); 
}