开发者

boost::asio::async_write does not complete its task

开发者 https://www.devze.com 2023-01-04 07:11 出处:网络
I\'m trying to figure out how asynchronous reads and writes work in boost asio by manipulating the echo example.Currently, I have a server that should, when sent a sentence, respond with only the firs

I'm trying to figure out how asynchronous reads and writes work in boost asio by manipulating the echo example. Currently, I have a server that should, when sent a sentence, respond with only the first word. However, the boost::asio::async_write never seems to complete even though the write handler is being called. Can someone please explain what's going on? Here's the code:

#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_cod开发者_如何学Ce& 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;
}

Thanks!


You're not using boost::asio::streambuf correctly, read the HTTP client example closely. For your code, you should do something like:

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

then use a separate boost::asio::streambuf for your response. As the previous answer also said, you're leaking memory. I'd suggest using boost::shared_ptr and shared_from_this.


  1. To avoid problems with possible memmory leaks involve with Session, You should consider using boost::enable_shared_from_this, like below:

    class session : public boost::enable_shared_from_this<session>
    

    Instead of use "this" use shared_from_this().

    Don't use delete this.

  2. You allocate table by new but I don`t see where memory is free.

    char* c = new char[bytes_transferred]; 
    

    delete c isn`t called

  3. Maybe better solution is using additional buffer m_bufferForRead instead of allocate table c.


As a could see you just don't close the socket and even don't delete the session. After you successful write and complete write handler, you leave the session object making memory leak. Also the char* c = new char[bytes_transferred]; make a memory leak as it is never used again, boost::asio::buffer don't deallocate the memory for you.

Simply change the write handler:

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

精彩评论

暂无评论...
验证码 换一张
取 消