从官方给出的示例中对于 boost::asio::ip::tcp::acceptor 类的使用,是直接使用构造函数进行构造对象,这一种方法用来学习是一个不错的方式。

但是要用它来做项目却是不能够满足我们的需求的,可它有相应的接口,可以让我们更灵活的使用它来做我们的项目。我们可以把这个accptor 的使用拆分开来,就是分成几个步骤来做。这样我们就可以在我们的项目中,在多个函数里面对它进行一步一步的生成。

 

简单的用法:

  1 #include <iostream>
  2 
  3 #include <boost/asio/io_service.hpp>
  4 #include <boost/shared_ptr.hpp>
  5 #include <boost/shared_array.hpp>
  6 #include <boost/make_shared.hpp>
  7 #include <boost/function.hpp>
  8 #include <boost/bind.hpp>
  9 #include <boost/asio/placeholders.hpp>
 10 #include <boost/asio/read.hpp>
 11 #include <boost/asio/write.hpp>
 12 #include <boost/asio/io_service.hpp>
 13 #include <boost/asio/ip/tcp.hpp>
 14 
 15 void async_accept();
 16 void handle_accept(boost::shared_ptr<boost::asio::ip::tcp::socket> new_conn, 
 17                    const boost::system::error_code &ec);
 18 void async_read(boost::shared_ptr<boost::asio::ip::tcp::socket> conn);
 19 void handle_msg(
 20     boost::shared_ptr<boost::asio::ip::tcp::socket> conn, 
 21     boost::shared_array<char> sa_len, 
 22     const boost::system::error_code &ec,
 23     std::size_t bytes_transfered);
 24 
 25 // 这里将这些对象,写为全局的,在实际的代码中,应该是一个类的成员变量或者其他方式存在
 26 boost::asio::io_service io_svc;    // io service 实例
 27 boost::asio::ip::address_v4 lis_ip;    // 默认监听本机所有IP
 28 boost::asio::ip::tcp::endpoint lis_ep(lis_ip, 20017);
 29 boost::asio::ip::tcp::acceptor acceptor(io_svc, lis_ep);
 30 
 31 int main(int argc, char *argv[])
 32 {
 33     async_accept();
 34 
 35     io_svc.run();
 36 
 37     return 0;
 38 }
 39 
 40 void async_accept()
 41 {
 42     boost::shared_ptr<boost::asio::ip::tcp::socket> new_sock
 43         = boost::make_shared<boost::asio::ip::tcp::socket>(boost::ref(io_svc));
 44     acceptor.async_accept(*new_sock, 
 45         boost::bind(handle_accept, new_sock, boost::asio::placeholders::error) );
 46 }
 47 
 48 void handle_accept(boost::shared_ptr<boost::asio::ip::tcp::socket> new_conn, 
 49                    const boost::system::error_code &ec)
 50 {
 51     if (ec != 0)
 52     {
 53         //LOG_INFO(get_logger(), "accept failed: " << ec.message());
 54         std::cout << "accept failed: " << ec.message() << std::endl;
 55         return ;
 56     }
 57     //LOG_INFO(get_logger(), "a new client connected." << new_conn->remote_endpoint());
 58     std::cout << "a new client connected." << new_conn->remote_endpoint() << std::endl;
 59 
 60     async_read(new_conn);
 61 
 62     // 处理下一个连接,每次处理完了之后,需要再次accept。
 63     // 否则BOOST 将只处理一次,然后结束监听。
 64     // 所以这里可以处理一个情况,就是当你要结束监听的时候,只要在这里return 
 65     // 那么io_service 的run() 函数就结束监听。但如果有其他的异步操作时,
 66     // run() 函数还是会继续运行的。
 67     async_accept();
 68 }
 69 
 70 void async_read(boost::shared_ptr<boost::asio::ip::tcp::socket> conn)
 71 {
 72     static const int PACKAGE_LENGTH = 6;
 73     // 数据报文长度为 6个字节
 74     boost::shared_array<char> sa_len(new char[PACKAGE_LENGTH]);
 75 
 76     // 回调函数
 77     boost::function<void (const boost::system::error_code &, std::size_t)> cb_msg_len;
 78     cb_msg_len = boost::bind(handle_msg, conn, sa_len, _1, _2);
 79 
 80     // 异步读,读一个报文的长度,boost::asio::async_read() 函数有个特点,
 81     // 它会将这里指定的buffer 缓冲区读满了才会去回调handle_msg 函数,
 82     boost::asio::async_read(*conn, 
 83         boost::asio::buffer(sa_len.get(), PACKAGE_LENGTH), cb_msg_len);
 84 
 85 }
 86 
 87 void handle_msg(
 88     boost::shared_ptr<boost::asio::ip::tcp::socket> conn, 
 89     boost::shared_array<char> sa_len, 
 90     const boost::system::error_code &ec,
 91     std::size_t bytes_transfered)
 92 {
 93     if (!conn->is_open())
 94     {
 95         //LOG_INFO(g_logger, "socket was not opened.");
 96         std::cout << "socket was not opened." << std::endl;
 97         //handle_dis_connect(conn);
 98         return ;
 99     }
100 
101     if (ec != 0)
102     {
103         if (ec == boost::asio::error::eof)
104             std::cout << "Disconnect from " << conn->remote_endpoint() << std::endl;
105         else
106             std::cout << "Error on receive: " << ec.message() << std::endl;
107 
108         //handle_dis_connect(the_conn);
109         return ;
110     }
111 
112     // 这里对接收到的数据做处理
113     // ...
114 
115     // 处理完了之后,类似accept 的异常调用一样,需要继续调用异步的读数据
116     // 同样的,如果要结束一个连接,正常的结束应该在这里return 调用。
117     // 当然了,使用socket 的close() shut_down() 函数也可以关闭这个连接。
118     async_read(conn);
119 }
View Code

相关文章: