boost::asio序列: UDP 通信

 为了能够测试,我将原来boost的示例中的端口13更改为60013,因为在13端口为daytime服务的专用端口: 如果强制使用运行时将会导致权限错误(ubuntu16.04)

1. 同步UDP 客户端

#include 
#include 
#include 

using boost::asio::ip::udp;

int main(int argc, char* argv[])
{
  try
  {
//    if (argc != 2)
//    {
//      std::cerr << "Usage: client " << std::endl;
//      return 1;
//    }

    boost::asio::io_context io_context;

//    udp::resolver resolver(io_context);
//    udp::endpoint receiver_endpoint =
//      *resolver.resolve(udp::v4(), argv[1], "daytime").begin();

    // 服务器IP 
    udp::endpoint receiver_endpoint(boost::asio::ip::address::from_string("127.0.0.1"), 60013);

    // 打开socket
    udp::socket socket(io_context);
    socket.open(udp::v4());

    // 同步发送数据
    boost::array send_buf  = {{ 0 }};
    socket.send_to(boost::asio::buffer(send_buf), receiver_endpoint);

   // 同步接收数据
    boost::array recv_buf;
    udp::endpoint sender_endpoint;
    size_t len = socket.receive_from(
        boost::asio::buffer(recv_buf), sender_endpoint);

    std::cout.write(recv_buf.data(), len);
  }
  catch (std::exception& e)
  {
    std::cerr << e.what() << std::endl;
  }

  return 0;
}

2. 同步UDP 服务器

#include 
#include 
#include 
#include 
#include 

using boost::asio::ip::udp;

std::string make_daytime_string()
{
  using namespace std; // For time_t, time and ctime;
  time_t now = time(0);
  return ctime(&now);
}

int main()
{
  try
  {
    boost::asio::io_context io_context;
    
    // UDP监听端口60013 
    udp::socket socket(io_context, udp::endpoint(udp::v4(), 60013));

    for (;;)
    {
      boost::array recv_buf;
      udp::endpoint remote_endpoint;
      boost::system::error_code error;
      socket.receive_from(boost::asio::buffer(recv_buf),
          remote_endpoint, 0, error);

      if (error && error != boost::asio::error::message_size)
        throw boost::system::system_error(error);

      std::string message = make_daytime_string();

      boost::system::error_code ignored_error;
      socket.send_to(boost::asio::buffer(message),
          remote_endpoint, 0, ignored_error);
    }
  }
  catch (std::exception& e)
  {
    std::cerr << e.what() << std::endl;
  }

  return 0;
}

3. 异步UDP服务器: 

#include 
#include 
#include 
#include 
#include 
#include 
#include 

using boost::asio::ip::udp;

std::string make_daytime_string()
{
  using namespace std; // For time_t, time and ctime;
  time_t now = time(0);
  return ctime(&now);
}

class udp_server
{
public:
  udp_server(boost::asio::io_context& io_context)
    : socket_(io_context, udp::endpoint(udp::v4(), 60013))
  {
    start_receive();
  }

private:
  void start_receive()
  {
    // 投递异步操作
      std::cout << "Asyn_receive_from start 0 " << std::endl;
    socket_.async_receive_from(
        boost::asio::buffer(recv_buffer_), remote_endpoint_,
        boost::bind(&udp_server::handle_receive, this,
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
    std::cout << "Asyn_receive_from start 1" << std::endl;
  }

  // 异步接收操作完成时调用的Handler
  void handle_receive(const boost::system::error_code& error,
      std::size_t /*bytes_transferred*/)
  {
    if (!error || error == boost::asio::error::message_size)
    {
        std::cout << "aysn_receive_handle 0" << std::endl;
      boost::shared_ptr message(
          new std::string(make_daytime_string()));

      std::cout << "asyn_send 0" << std::endl;
      socket_.async_send_to(boost::asio::buffer(*message), remote_endpoint_,
          boost::bind(&udp_server::handle_send, this, message,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
      std::cout << "asyn_send 1" << std::endl;

      start_receive();
      std::cout << "aysn_receive_handle 1" << std::endl;
    }
  }

  // 异步发送操作完成时调用的Handler
  void handle_send(boost::shared_ptr /*message*/,
      const boost::system::error_code& /*error*/,
      std::size_t /*bytes_transferred*/)
  {
      std::cout << "aysn_send_handle 0" << std::endl;
  }

  udp::socket socket_;
  udp::endpoint remote_endpoint_;
  boost::array recv_buffer_;
};

int main()
{
  try
  {
    boost::asio::io_context io_context;
    udp_server server(io_context);
    io_context.run(); // 在异步操作中,要在合适的地方调用run(),否则,会直接退出主函数
  }
  catch (std::exception& e)
  {
    std::cerr << e.what() << std::endl;
  }

  return 0;
}

注意,查看打印日志的顺序,以充分理解异步:先提交发送/接收请求,当请求正常/非正常完成时,调用对应的Handler,并且将相应的信息告诉任务提交者

boost::asio序列: UDP 通信_第1张图片

你可能感兴趣的:(c++,QT,BOOST)