asio之tcp

追求适度,才能走向成功;人在顶峰,迈步就是下坡;身在低谷,抬足既是登高;弦,绷得太紧会断;人,思虑过度会疯;水至清无鱼,人至真无友,山至高无树;适度,不是中庸,而是一种明智的生活态度。

导读:本篇文章讲解 asio之tcp,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

asio库支持TCP、UDP和工CMP等通信协议,它在名字空间boost::asio :: ip里提供了大量的网络通信方面的函数和类,很好地封装了原始的Socket API,展现给asio用户一个方便易用且健壮的网络通信库,下面的论述主要针对使用最广泛的TCP协议。

类ip ::tcp是asio网络通信(TCP)部分主要的类,表示TCP协议。但它本身并没有太多的功能,而是定义了数个用于TCP通信的typedef类型,用来协作完成网络通信。这些typedef包括端点类endpoint、套接字类socket、流类iostream,以及接受器acceptor、解析器resolver等。从某种程度上来看,ip::tcp类更像是一个名字空间。

class tcp
{
public:
  /// The type of a TCP endpoint.
  typedef basic_endpoint<tcp> endpoint;

  /// Construct to represent the IPv4 TCP protocol.
  static tcp v4() BOOST_ASIO_NOEXCEPT
  {
    return tcp(BOOST_ASIO_OS_DEF(AF_INET));
  }

  /// Construct to represent the IPv6 TCP protocol.
  static tcp v6() BOOST_ASIO_NOEXCEPT
  {
    return tcp(BOOST_ASIO_OS_DEF(AF_INET6));
  }

  /// Obtain an identifier for the type of the protocol.
  int type() const BOOST_ASIO_NOEXCEPT
  {
    return BOOST_ASIO_OS_DEF(SOCK_STREAM);
  }

  /// Obtain an identifier for the protocol.
  int protocol() const BOOST_ASIO_NOEXCEPT
  {
    return BOOST_ASIO_OS_DEF(IPPROTO_TCP);
  }

  /// Obtain an identifier for the protocol family.
  int family() const BOOST_ASIO_NOEXCEPT
  {
    return family_;
  }

  /// The TCP socket type.
  typedef basic_stream_socket<tcp> socket;

  /// The TCP acceptor type.
  typedef basic_socket_acceptor<tcp> acceptor;

  /// The TCP resolver type.
  typedef basic_resolver<tcp> resolver;

#if !defined(BOOST_ASIO_NO_IOSTREAM)
  /// The TCP iostream type.
  typedef basic_socket_iostream<tcp> iostream;
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)

  /// Socket option for disabling the Nagle algorithm.
  /**
   * Implements the IPPROTO_TCP/TCP_NODELAY socket option.
   *
   * @par Examples
   * Setting the option:
   * @code
   * boost::asio::ip::tcp::socket socket(my_context);
   * ...
   * boost::asio::ip::tcp::no_delay option(true);
   * socket.set_option(option);
   * @endcode
   *
   * @par
   * Getting the current option value:
   * @code
   * boost::asio::ip::tcp::socket socket(my_context);
   * ...
   * boost::asio::ip::tcp::no_delay option;
   * socket.get_option(option);
   * bool is_set = option.value();
   * @endcode
   *
   * @par Concepts:
   * Socket_Option, Boolean_Socket_Option.
   */
#if defined(GENERATING_DOCUMENTATION)
  typedef implementation_defined no_delay;
#else
  typedef boost::asio::detail::socket_option::boolean<
    BOOST_ASIO_OS_DEF(IPPROTO_TCP), BOOST_ASIO_OS_DEF(TCP_NODELAY)> no_delay;
#endif

  /// Compare two protocols for equality.
  friend bool operator==(const tcp& p1, const tcp& p2)
  {
    return p1.family_ == p2.family_;
  }

  /// Compare two protocols for inequality.
  friend bool operator!=(const tcp& p1, const tcp& p2)
  {
    return p1.family_ != p2.family_;
  }

private:
  // Construct with a specific family.
  explicit tcp(int protocol_family) BOOST_ASIO_NOEXCEPT
    : family_(protocol_family)
  {
  }

  int family_;
};

ip : :tcp 的内部类型endpoint、socket、acceptor和 resolver是 asio库TCP通信中最核心的一组类,它们封装了socket 的连接、断开、数据收发和地址解析等功能,使用它们可以很容易地编写出socket程序。

address

IP卫地址独立于TCP、UDP等通信协议,asio库使用类ip : : address来表示IP地址;可以同时支持工Pv4和工Pv6两种地址,它的类摘要如下:

class address
{
    public:
    address();
    address(const address&other);

    bool    is_v4();
    bool    is_v6();
    bool    is_loopback();//环回地址

    ip::address_v4 to_v4()const;
    ip::address_v6 to_v6()const;


    string  to_string();
    static  address from_string(const char* str);
    static  address from_string(const string& str);

    ....
}

addreee类最重要的方法是静态成员函数from_string (),它是一个工厂函数,可以从字符串产生IP地址,地址的版本则可以用is_v4()和is_v6()来检测。相应地,address也有一个to_string ()函数,可以把工F地址转换为字符串。

示例:

ip::address addr;
addr=addr.from_strng("127.0.0.1");
assert(addrss.is_v4());

endpoint

有了IP地址,再加上通信用的端口号就构成了一个socket端点,在asio库中用ip: :tcp: :endpoint来表示。

template<typename InternetProtocol>
class basic_endpoint{
    typedef InternetProtocol protocol_type;
    basic_endpoint(const InternetProtocol&internet_protocol,
    unsigned short port_num);
    basic_endpoint(const ip::address&addr, unsigned short port_num)

    basic_endpoint(basic_endpoint&&other);
    basic_endpoint&operator==(const basic_endpoint&other);
    protocol_type protocol();
    unsigned short port()const;

    ....

}

endpoint的主要用法是通过构造函数创建一个可用于socket通信的端点对象,端点的地址和端口号可以用address ()和 port()获得,例如:

ip::address addr;
addr=addr.from_string("127.0.0.1");

ip::tcp::endpoint(addr,6688)

socket

template<typename Protocol,typename ...AS>
class basic_stream_socket
{
    public:
    typedef Protocol      Protocol_type;
    typedef typename Protocol::endpoint  endpoint_type;

    //
    basic_stream_socket(io_service&io);
    basic_stream_socket(io_service&io,
    const Protocol_type&Protocol);
    basic_stream_socket(io_service&io,
    const endpoint_type& endpoint);
    
    //打开
    void open(const Protocol_type&protocol==Protocol_type());
    bool is_open()const;
    void close();
    void shutdown();
    void cancel();

    //可读字节数
    std::size_t    available()const;
    //绑定endpoint;
    void           connect(const endpoint_type&peer_endpoint)
    void           connect(const endpoint_type&peer_endpoint,handler);
    //设置socket
    void           set_option(const SettableSocketOptions&option);
    void           get_option(GettableSocketOption&option);
    ...
    //发送数据
    std::size       receive(const MutableBuffer*buffer);
    void            async_receive(const MutableBuffer*buffer,handler);
    ...

         
};

socket可以在构造时就指定使用的协议或者endpoint,或者稍后调用成员函数connect ()。连接成功后可以用local_endpoint()和remote_endpoint()获得连接两端的端点信息,用 available ()获取可读取的字节数,用 receive ( )/read _some ( )和send ( ) /write_some ( )读写数据,当操作完成后使用close ()函数关闭socket。如果不关闭socket,那么在 socket对象析构时也会自动调用close()关闭。

accptor

acceptor类对应Socket API的 accept ()函数功能,它用于服务器端,在指定的端口号接受连接,必须配合socket类才能完成通信。

template<typename Protocol,typename... AS>
class basic_socket_acceptor
{
    public:
    typedef Protocol protocl_type;
    typedef typename Protocol::endpoint endpoint_type;
    //
    explicit basic_socket_acceptor(io_service&io_service);
    basic_socket_acceptor(io_service&io_service,
    const protocol_type&protocol);
    
    //
    accept(socket &peer);
    void async_accept(socket&peer,handler);
    ...
};

acceptor可以像传统socket API那样使用,open()打开端口,bind ()绑定再用listen ()监听端口,但更方便的是使用它的构造函数,传入endpoint直接完成这三个动作在开始监听之后,调用accept ()就可以接受新的连接,连接成功的socket在函数参数里以引用的形式输出。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之家整理,本文链接:https://www.bmabk.com/index.php/post/129666.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之家——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!