2010-06-17 172 views
0

我想通過操縱回聲示例來了解異步讀寫如何在boost asio中工作。目前,我有一臺服務器應該在發送一個句子時只回應第一個單詞。然而,boost :: asio :: async_write似乎從未完成,即使正在調用寫入處理程序。有人可以解釋發生了什麼事嗎?這裏的代碼:boost :: asio :: async_write沒有完成其任務

#include <cstdlib> 
#include <iostream> 
#include <boost/bind.hpp> 
#include <boost/asio.hpp> 

using boost::asio::ip::tcp; 

class session 
{ 
public: 
    session(boost::asio::io_service& io_service) 
    : socket_(io_service) 
    { 
    } 

    tcp::socket& socket() 
    { 
    return socket_; 
    } 

    void start() 
    { 
std::cout<<"starting"<<std::endl; 
    boost::asio::async_read_until(socket_, buffer, ' ', 
     boost::bind(&session::handle_read, this, 
      boost::asio::placeholders::error, 
      boost::asio::placeholders::bytes_transferred)); 
    } 

    void handle_read(const boost::system::error_code& error, 
     size_t bytes_transferred) 
    { 

// std::ostringstream ss; 
// ss<<&buffer; 

char* c = new char[bytes_transferred]; 

//std::string s; 
buffer.sgetn(c,bytes_transferred); 
std::cout<<"data: "<< c<<" bytes: "<<bytes_transferred<<std::endl; 

if (!error) 
    { 
     boost::asio::async_write(socket_, 
      boost::asio::buffer(c,bytes_transferred), 
      boost::bind(&session::handle_write, this, 
      boost::asio::placeholders::error)); 
    } 
    else 
    { 
     delete this; 
    } 
    } 

    void handle_write(const boost::system::error_code& error) 
    { 
std::cout<<"handling write"<<std::endl; 
    if (!error) 
    { 
    } 
    else 
    { 
     delete this; 
    } 
    } 

private: 
    tcp::socket socket_; 
    boost::asio::streambuf buffer; 
}; 

class server 
{ 
public: 
    server(boost::asio::io_service& io_service, short port) 
    : io_service_(io_service), 
     acceptor_(io_service, tcp::endpoint(tcp::v4(), port)) 
    { 
    session* new_session = new session(io_service_); 
    acceptor_.async_accept(new_session->socket(), 
     boost::bind(&server::handle_accept, this, new_session, 
      boost::asio::placeholders::error)); 
    } 

    void handle_accept(session* new_session, 
     const boost::system::error_code& error) 
    { 
    if (!error) 
    { 
     new_session->start(); 
     new_session = new session(io_service_); 
     acceptor_.async_accept(new_session->socket(), 
      boost::bind(&server::handle_accept, this, new_session, 
      boost::asio::placeholders::error)); 
    } 
    else 
    { 
     delete new_session; 
    } 
    } 

private: 
    boost::asio::io_service& io_service_; 
    tcp::acceptor acceptor_; 
}; 

int main(int argc, char* argv[]) 
{ 
    try 
    { 
    if (argc != 2) 
    { 
     std::cerr << "Usage: async_tcp_echo_server <port>\n"; 
     return 1; 
    } 

    boost::asio::io_service io_service; 

    using namespace std; // For atoi. 
    server s(io_service, atoi(argv[1])); 

    io_service.run(); 
    } 
    catch (std::exception& e) 
    { 
    std::cerr << "Exception: " << e.what() << "\n"; 
    } 

    return 0; 
} 

謝謝!

回答

0

正如你可以看到你只是不關閉套接字,甚至不刪除會話。 成功寫入並完成寫入處理程序後,會使會話對象內存泄漏。此外char* c = new char[bytes_transferred];會造成內存泄漏,因爲它不會再次使用,boost::asio::buffer不會爲您取消分配內存。

只需更改寫入處理程序:

void handle_write(const boost::system::error_code& error) 
{ 
    std::cout<<"handling write and exiting."<<std::endl; 
    delete this; 
} 
+0

如果我這樣做,我只是得到文件異常結束 – user368831 2010-06-17 15:07:34

+0

你從哪裏得到異常?對我來說,這個代碼運行良好(提升1.40)。 – Arpegius 2010-06-19 10:16:53

2

你不使用boost ::支持ASIO ::流緩衝正確,仔細閱讀了HTTP client example。對於你的代碼,你應該這樣做:

buffer.commit(bytes_transferred); 
std::istream is(&buffer); 
std::string data; 
is >> data; 
std::cout << "data: " << data << " bytes: " << bytes_transferred << std::endl; 

然後使用單獨的boost :: asio :: streambuf作爲響應。正如之前的回答也表示,你正在泄漏記憶。我建議使用boost :: shared_ptr和shared_from_this。

+0

我知道這是舊的,但只是供參考,在您發佈的示例中調用提交緩衝區沒有任何關係,所以您的註釋和部分代碼很混亂。 – 2015-04-24 20:45:02

0
  1. 爲了避免可能出現的泄漏memmory問題,會議涉及到,你應該考慮使用boost::enable_shared_from_this,象下面這樣:

    class session : public boost::enable_shared_from_this<session> 
    

    改爲使用的 「本」 使用shared_from_this()

    請勿使用delete this

  2. 你用new分配表,但是我看不到內存是空閒的。

    char* c = new char[bytes_transferred]; 
    

    delete c isn`t稱爲

  3. 也許更好的解決方案是使用額外的緩衝m_bufferForRead代替分配表c

相關問題