boost :: asio :: async_write没有完成其任务

boost :: asio :: async_write没有完成其任务

问题描述:

我想通过操纵回声示例来了解异步读写如何在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; 
} 

谢谢!

正如你可以看到你只是不关闭套接字,甚至不删除会话。 成功写入并完成写入处理程序后,会使会话对象内存泄漏。此外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

你不使用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

  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