美文网首页C++2.0
Boost(二)

Boost(二)

作者: 芒鞋儿 | 来源:发表于2018-10-24 15:50 被阅读6次
    boost::asio

    asio 主要用于网络通信,封装了socket API, 包含了TCP, ICMP,UDP等协议,支持串口读写,定时器,SSL等。
    asio 采用前摄器设计模式(Proactor) 实现了可移植的异步或同步IO操作,不要求多线程和锁定,避免了线程的竞争等问题。

    • 定时器:deadline_timer:
      定时器一旦创建就开始计时,可用wait()或async_wait()异步等待,终止时调用handler函数。
      如果不指定终止时间,可用成员函数expires_at(), expires_from_now()指定绝对或相对的终止时间。

    ip::tcp 类是asio 网络通信(TCP)主要的类,定义了数个typedef 类,包括:endpoint, socket, iostream, acceptor, resolver(解析器)等

    • ip地址和端口
      address 类用法示例:
      ip::address addr;
      addr = addr.from_string("127.0.0.1");
      cout << addr.to_string() << endl;
    

    加上端口:

      ip::tcp::endpoint ep(addr, 6688) //创建断点对象,6688 为端口号
      assert(ep.address()== addr);
      assert(ep.port() == 6688);
    

    ip::tcp 的内部类型socket, acceptor, 以及 resolver 是asio 库 TCP通信中最核心的一组类,封装了socket的链接,断开和数据首发功能,使用它们能比较方便编写socket的程序。
    用法:成员函数connect() 连接到一个指定的通信端点,连接成功后用local_endpoint() 和 remote_endpoint() 获得连接两端的端点信息, read_some() 和 write_some() 阻塞读写数据,操作完成后用close()关闭socket.
    acceptor 类对应accept() 等函数,用于服务器端; resolver 类对应 getaddrinfo() 等函数,用于客户端。

    int main()
    try{
      cout << "server: " << endl;
      io_service ios;  //asio 必须的io_service 对象
    
      ip::tcp::acceptor acceptor (ios, ip::tcp::endpoint(ip::tcp::v4(), 6688); 
      // 创建ipv4的对象,并打开6688端口
    
      cout << acceptor.local_endpoint().address() << endl;
    
      while(true)
      {
          ip::tcp::socket sock(ios); // 一个socket 对象
          acceptor.accept (sock);  // 等待连接
    
          cout << "client"; 
          cout << sock.remote_endpoint().address() << endl;
    
          sock.write_some(buffer("hello asio")); // 发送数据
      }
    
    }
    catch (std::exception& e)
    {  
        cout << e.what() << endl;
    }
    

    异步socket 处理的例子:

      class server
      {
        private:  
            io_service &ios;
            ip::tcp::acceptor acceptor;
            typedef shared_ptr<ip::tcp::socket> sock_ptr;
         public:
            server(io_service& io): ios(io), acceptor(ios,ip::tcp::endpoint(ip::tcp::v4(),6688)){     start();  }
    
      }
    

    然后用server()函数启动异步服务:

    void start()
    {
      socket_ptr sock(new ip::tcp::socket(ios);
      acceptor.async_accept(*sock, bind(&server::accept_handler, this, placeholder::error, sock));
    }
    

    shared_ptr 可以在程序的整个生命周期中存在。

    TCP 发生连接时候,server::accept_handler()被调用,使用socket()发送数据

    void accept_handler(const system::error_code& ec, sock_pt sock)
    {
      if(ec) { return;} //监测错误码
      cout << "client:";
      cout << sock->remote_endpoint().address() << endl; //连接的客户端信息
      sock -> async_write_some(buffer("hello asio"), bind(&server::write_handler, this, placeholder::error));
    
      start();  //启动异步接受连接
    }
    
    • 查询网络地址
      resolver 使用内部类query 和 iterator 查询IP, 程序片段:
    void resolv_connect(ip::tcp::socket &sock, const char* name, int port)
    {
        ip::tcp::resolver rlv(sock.get_io_service());  //resolver 对象
        ip::tcp::resolver::query qry(name, lexical_cast<string>(port)); 
        // lexical_cast 用于把端口号转为字符串
    
        // 迭代端点,遍历query
        ip::tcp::resolver::iterator iter = rlv.resolve(qry);
        ip::tcp::resolver::iterator end;
        system::error_code ec = error::host_not_found;
        for( ; ec && iter!= end; ++iter)
        {
            sock.close();
            sock.connect(*iter,ec); //连接
        }
        if (ec) { throw syste::system_error(ec); }
        cout << "connect success." <<endl;
    }
    
    thread 库和asio 库均可以用于并发编程,但是解决问题的途径不同,thread 使用线程机制,无需OS内核的干预,只要线程同步做好。而asio 使用异步时间处理机制,与OS的内核密切相关,需要对OS的底层机制有一定了解,比线程更难调试,而把异步处理交给OS,从而获得更高运行性能。(EOS里面那么多asio,哎,除了提高性能的原因,是否也有故意提高调试门槛的味道?)
    
    
    
    
    

    相关文章

      网友评论

        本文标题:Boost(二)

        本文链接:https://www.haomeiwen.com/subject/fayttqtx.html