什么是端口查询
在进行网络通信时,需要知道对方的确切地址,即端口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.com
、baidu.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
查询对应端口,这两种操作的结果均可以直接给后续的通信接口使用。
网友评论