端口查询baisc_resolver

什么是端口查询

在进行网络通信时,需要知道对方的确切地址,即端口endpoint,但是很多情况下只知道要通信的主机名及其服务名,这时就可以使用端口查询得到具体的端口。
譬如在google.com上提供了一个http服务,那么就需要使用主机名google.com和服务名http来得到与之对应的端口。

概述

我们知道,从主机得到具体的IP地址是需要和DNS服务器进行通信的,所以在Boost.Asio中提供了ip::resolver_service来实现端口查询,具体的查询动作封装在basic_resolver中,可以理解为一个有限度的socket,能够使用同步或者异步的方式进行查询,而查询参数则封装为ip::basic_resolver_query

查询参数ip::basic_resolver_query

可以指定要查询的主机名、服务名以及查询设定:

  • 主机名
    本地为localhost,远程的一般为域名,譬如google.combaidu.com等,在Windows上可以配置host文件来将域名映射到对应的IP地址
  • 服务名
    有一些服务名和端口是对应关系,可以直接根据服务得到端口,具体的对应关系见Service Name and Transport Protocol Port Number Registry
  • 查询设定
    查询设定以bitmask呈现,有以下几项:
canonical_name;//Determine the canonical name of the host specified in the query
passive;// Indicate that returned endpoint is intended for use as a locally bound socket endpoint
numeric_host;  //地址形式的主机名,不再进行对应查询
numeric_service; //数值形式的服务名,不再进行对应查询
v4_mapped;  //如果查询IPv6,在没有查询到IPv6地址时,返回IPv4-mapped的IPv6地址
all_matching; //如果设定了v4_mapped,则返回所有匹配的IPv4和IPv6地址
address_configured;//没有loopback地址配置时,只返回对应的IPv4或者IPv6

当构造一个本地查询时,默认查询设定为passive|address_configured,当构造远程主机查询时,默认的查询设定为address_configured

查询结果及迭代器

由于端口查询结果可能为多个,所以Boost.Asio进行了封装:

  • 查询结果basic_resolver_entry
    包含了查询出来的端口,以及查询入参:主机名、服务名。
  • 查询结果迭代器basic_resolver_iterator
    可以直接构造,也可以由resolver来生成,用来进行结果的遍历动作

查询动作baisc_resolver

可以根据io_service直接构造对应的resolver,提供了以下方法:

  • resolve
    同步查询动作,返回查询结果迭代器
  • async_resolve
    异步查询动作,异步Handler原型为void handler(错误码,结果迭代器)
  • cancel
    取消异步查询动作

使用示例

同步查询示例

void test_tcp_resolver()
{
    io_service io;

    ip::tcp::resolver resolver(io);
    boost::system::error_code ec;

    auto endpoint_iter = resolver.resolve({ "google.com","https" }, ec);
    if (!ec)
    {
        while (endpoint_iter != ip::tcp::resolver::iterator())
        {
            std::cout << endpoint_iter->endpoint() << "\n";
            endpoint_iter++;
        }
    }
}

异步查询示例

void test_tcp_async_resolver()
{
    io_service io;

    ip::tcp::resolver resolver(io);
    boost::system::error_code ec;

    resolver.async_resolve({ "google.com","https" },[](auto ec,auto iter){
        if (!ec)
        {
            std::cout<< iter->endpoint()<<"\n";
            //可以对iter进行修改,使其结束
        }
    });

    io.run();
}

总结

在已知目标端口的情况下可以直接构造端口,如果只是知道主机名可以使用resolver查询对应端口,这两种操作的结果均可以直接给后续的通信接口使用。

你可能感兴趣的:(端口查询baisc_resolver)