【问题标题】:Boost::asio TCP server -- reading a message from the clientBoost::asio TCP 服务器——从客户端读取消息
【发布时间】:2014-08-19 21:08:37
【问题描述】:

我正在尝试使用 boost::asio 创建我的第一个 TCP 服务器。服务器将监听客户端,如果它收到消息“MESSAGE_SEND_A:”,它应该将以下消息发送回客户端:“A|A|A|A|A|A”。如果它收到消息“MESSAGE_SEND_B:”,则相应地它应该向客户端发送另一条消息:“B|B|B|B|B|B”。

现在,我一直在研究 Boost TCP server 的教程,也差不多明白了:

编辑:基于 cmets 重写代码

 #include <ctime>
 #include <iostream>
 #include <string>
 #include <boost/bind.hpp>
 #include <boost/shared_ptr.hpp>
 #include <boost/enable_shared_from_this.hpp>
 #include <boost/asio.hpp>

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

 class tcp_connection : public boost::enable_shared_from_this<tcp_connection>
 {
   public:

   typedef boost::shared_ptr<tcp_connection> pointer;

   static pointer create(boost::asio::io_service& io_service)
   {
      return pointer(new tcp_connection(io_service));
   }

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

   void start()
   { 
      // Start reading messages from the server
      start_read();

      if (messageFromClient_ == "MESSAGEA:")
      {
         messageToClient_ = "A|A|A|A|A|A|A|A|A|A";
      }

      else if (messageFromClient_ == "MESSAGEB:")
      {
         messageToClient_ = "B|B|B|B|B|B|B|B|B|B";
      }

      boost::asio::async_write(socket_, boost::asio::buffer(messageToClient_),
          boost::bind(&tcp_connection::handle_write, shared_from_this(),
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
   }

   private:

   tcp_connection(boost::asio::io_service& io_service) : socket_(io_service)
   {
   }

   // Reading messages from the server
   void start_read()
   {
      // Start an asynchronous operation to read a newline-delimited message.
      // When read, handle_read should kick in
      boost::asio::async_read(socket_, input_buffer_,
          boost::asio::transfer_at_least(1),
          boost::bind(&tcp_connection::handle_read, this,
          boost::asio::placeholders::error));
   }

   // When stream is received, handle the message from the client
   void handle_read(const boost::system::error_code& ec)
   {
      //if (stopped_)
      //  return;

      // Making the message nil every time the function starts. Do I need it???????
      messageFromClient_ = "";

      if (!ec)
      {
          // Extract the newline-delimited message from the buffer.
          std::string line;
          std::istream is(&input_buffer_);
          std::getline(is, line);

          // Empty messages are heartbeats and so ignored.
          if (!line.empty())
          {
              messageFromClient_ = line;
              std::cout << "Received: " << line << "\n";
          }

          start_read();
       }
       else
       {
        std::cout << "Error on receive: " << ec.message() << "\n";
       }
   }

   void handle_write(const boost::system::error_code& /*error*/,
     size_t /*bytes_transferred*/)
   {
   }

   tcp::socket socket_;
   std::string messageToClient_;
   boost::asio::streambuf input_buffer_;
   std::string messageFromClient_;
 };



 class tcp_server
 {
 public:

 tcp_server(boost::asio::io_service& io_service)
   : acceptor_(io_service, tcp::endpoint(tcp::v4(), 7767))
 {
    start_accept();
 }

 private:

 void start_accept()
 {
    tcp_connection::pointer new_connection =
        tcp_connection::create(acceptor_.get_io_service());

    acceptor_.async_accept(new_connection->socket(),
        boost::bind(&tcp_server::handle_accept, this, new_connection,
        boost::asio::placeholders::error));
 }

 void handle_user_read(const boost::system::error_code& err,
    std::size_t bytes_transferred)
 {
 }

 void handle_accept(tcp_connection::pointer new_connection,
    const boost::system::error_code& error)
 {
    if (!error)
    {
       new_connection->start();

       start_accept();
    }
 }

 tcp::acceptor acceptor_;
 };


 int main()
 {
    try
    {
       boost::asio::io_service io_service;
       tcp_server server(io_service);
       io_service.run();
    }
    catch (std::exception& e)
    {
       std::cerr << e.what() << std::endl;
    }

    return 0;
  }

代码在 Qt 上编译得很好,但是给了我:

 Error on receive: Operation canceled

每次我尝试从我的客户端 (iPad) 发送消息时。

谢谢!

【问题讨论】:

  • 您的服务器需要从handle_accept() 中接受的套接字启动async_read(),然后以适当的消息响应或处理任何错误。
  • 感谢您的回复!我正在重写我的代码,如果它有效,我会告诉你。最佳

标签: c++ boost tcp boost-asio


【解决方案1】:

函数 start() 应该从套接字异步读取,同时在收到数据时调用 handle_read() 函数。 请查看此示例: http://www.boost.org/doc/libs/1_45_0/doc/html/boost_asio/example/timeouts/async_tcp_client.cpp

【讨论】:

  • 谢谢!您提供链接的示例非常有帮助。我正在重写我的代码,如果它有效,我会告诉你。最好的。
  • 再次感谢您。我改变了我的代码。请参阅原始消息中的编辑代码。现在,我正在尝试使用我的 iPad 作为客户端向服务器发送消息和从服务器接收消息。我在 python 中有一个简单的测试程序,它可以工作。所以,我知道我的客户很好。但是,当我尝试将它连接到运行代码的 Qt 时,我得到这个:Error on receive: Operation canceled 是我的 boost 代码有问题还是我仔细查看了客户端?谢谢!
  • 通过使用这个来解决它:shared_from_this() in async_read()。服务器仍然没有发送消息,但至少它在进行中。
  • 将 async_write 移动到 handle_read() 函数中,一切都像一个魅力。山姆和埃里克,非常感谢您的大力帮助!
猜你喜欢
  • 1970-01-01
  • 2013-03-02
  • 1970-01-01
  • 1970-01-01
  • 2016-03-18
  • 2021-04-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-08
相关资源
最近更新 更多