2013-02-28 71 views
1

在我的應用程序中,我發送和接收大量消息並表現爲服務器。 在我檢查客戶端的會話超時的意思。 當我在應用程序中不使用async_wait時,我的程序正常工作。但是當我使用async_wait時,那麼在發送和接收大約100,000到200,000條消息之後,我的應用程序就會崩潰並出現以下錯誤。發送批量消息時出現BOOST :: async_wait錯誤

"terminate called after throwing an instance of 'boost::exception_detail:: 
clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >' what(): asio.ssl error" 

無論何時服務器收到來自客戶端的任何消息,就會調用start()

void Connection::start() 
    { 
    this->resetTimer(); 

    memset(_messageHeader.c_array(), 0, 8); 
    boost::asio::async_read(_socket, 
     boost::asio::buffer(_messageHeader, 8), 
     _strand.wrap(
      boost::bind(
      &Connection::handleRead, 
      shared_from_this(), 
      boost::asio::placeholders::error, 
      boost::asio::placeholders::bytes_transferred 
      ) 
     ) 
     ); 
    } 

    void Connection::handleRead(const boost::system::error_code& e, 
     std::size_t bytesTransferred) 
    { 
    if (!e) { 

     BOOST_STATIC_ASSERT(sizeof(MessageHeader) == 8); 

     Message message ; 
     message.header.fromString(
      std::string(_messageHeader.data(), 
      sizeof(MessageHeader) 
      ) 
     ); 
     uint32_t type = message.header.type; 
     uint32_t length = message.header.length; 

     boost::asio::async_read(_socket, 
      boost::asio::buffer(_buffer, message.header.length), 
      _strand.wrap(
      boost::bind(
       &Connection::messageRead, 
       shared_from_this(), 
       boost::asio::placeholders::error, 
       boost::asio::placeholders::bytes_transferred, 
       type, 
       length 
      ) 
      ) 
     ); 
     } 
    else { 
     this->close(); 
    } 
    } 

void Connection::messageRead(const boost::system::error_code& e, 
    std::size_t bytesTransferred, uint32_t type, uint32_t length) 
{ 
    if (!e) { 

    Message message; 

    message.header.type = type; 
    message.header.length = length; 

    message.body = std::string(_buffer.data(), message.header.length); 
    memset(_buffer.c_array(), 0, message.header.length); 

    _timeoutCount = 0; 

    this->start(); 
    } 
    else { 
    this->close(); 
    } 
} 


void Connection::sendResponse(const Message& response) 
{ 
    std::string stringToSend(response.toString()); 

    boost::system::error_code error; 
    boost::asio::ip::tcp::endpoint endpoint = socket().remote_endpoint(error); 

    if (error) { 
    this->close(); 
    } 

    _strand.post(
     boost::bind(
     &CclConnection::writeImpl, 
     shared_from_this(), 
     stringToSend 
     ) 
     ); 
} 


void Connection::writeImpl(const std::string &message) 
{ 
    _outbox.push_back(message); 
    if (_outbox.size() > 1) { 
    return; 
    } 
    this->write(); 
} 

void Connection::write() 
{ 
    const std::string& message = _outbox[0]; 
    boost::asio::async_write(
     _socket, 
     boost::asio::buffer(message.c_str(), message.size()), 
     _strand.wrap(
     boost::bind(
      &Connection::writeHandler, 
      shared_from_this(), 
      boost::asio::placeholders::error, 
      boost::asio::placeholders::bytes_transferred 
      ) 
     ) 
     ); 
} 

void Connection::writeHandler(
    const boost::system::error_code& e, 
    const size_t bytesTransferred 
    ) 
{ 
    _outbox.pop_front(); 

    if (e) { 
    this->close(); 
    } 
    if (!_outbox.empty()) { 
    this->write(); 
    } 
} 

// close connection 
void Connection::close() 
{ 
    boost::system::error_code ignoredCode; 
    socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both, 
     ignoredCode); 
    } 

void Connection::resetTimer() 
{ 
    if (Context::getSessionTimeout() > 0) 
    { 
    // timer of 10 seconds 
    _timer.expires_from_now(10); 
    _timer.async_wait(
     _strand.wrap(
      boost::bind(&Connection::handleTimeout, 
      shared_from_this(), 
      boost::asio::placeholders::error) 
      ) 
     ); 
    } 
} 


void Connection::handleTimeout(const boost::system::error_code &e) 
{ 
    if (!_loggedIn) 
    return; 

    if (!e) 
    { 
    boost::system::error_code ec; 
    boost::asio::ip::tcp::endpoint endpoint = socket().remote_endpoint(ec); 

    if (ec) 
    { 
     this->close(); 
     return; 
    } 
    else 
    { 
     _timeoutCount++; 

     std::string ping = "ping"; 
     Message message(REQ_PING, ping); 
     this->sendResponse(message); 

     // no activity for quite some time now 
     // so we just disconnect the session 
     if (_timeoutCount > 30) 
     { 
     ERROR_1(TIMEOUT_OCCURED); 
     this->close(); 
     } 
     else 
     this->start(); 
    } 
    } 
} 
+0

我敢打賭你在某個地方有未定義的行爲。發佈[sscce](http://sscce.org),我們可以提供幫助。此外,這與您的[上一個問題](http://stackoverflow.com/q/14869128/283302)非常相似,因此您可能想澄清一下不同之處。 – 2013-02-28 22:49:41

+0

也不是一個*調試我的代碼*網站,請指出你已經嘗試過。 – 2013-02-28 22:50:31

+0

在畝先前的問題。我沒有得到解決方案。 – user1841046 2013-03-01 07:17:39

回答

0

async_wait處理程序通過調用Connection::start()

else 
{ 
    _timeoutCount++; 

    std::string ping = "ping"; 
    Message message(REQ_PING, ping); 
    this->sendResponse(message); 

    // no activity for quite some time now 
    // so we just disconnect the session 
    if (_timeoutCount > 30) 
    { 
    ERROR_1(TIMEOUT_OCCURED); 
    this->close(); 
    } 
    else 
    this->start(); // this will perform an async_read 
} 

這是錯誤的調度每次async_read,我懷疑你想要什麼。你的程序在ill-formed時調用後續的async_read操作已經有一個未完成的套接字。我建議不要調用Connection::start(),而應重新設置async_wait處理程序中的計時器,並再次調用async_wait