Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What type of asio resolver object should I use?

Tags:

boost-asio

I am a little confused about which type of resolver I should use for a side project I am working on. I am not finding the answer in the asio documentation.

I know that DNS can work with both UDP or TCP and that larger responses are generally sent over TCP.

asio offers both ip::tcp::resolver and ip::udp::resolver.

  • Can I use them interchangeably?
  • After I have resolved the name to an endpoint, I plan to connect with a TCP socket. Does that mean I have to use a ip::tcp::resolver?

If there are in fact interchangeable:

  • Is there a performance benefit to using the UDP resolver?
  • Is there a some other benefit to using the TCP resolver?
  • If I use UDP resolver, do I need to deal with the response being too large for the UDP lookup and retry with TCP? (I expect to connect to a CDN that will resolve to multiple IP addresses per host)
like image 752
Colin Andrews Avatar asked Nov 22 '16 20:11

Colin Andrews


1 Answers

Use the resolver that has the same protocol as the socket. For example, tcp::socket::connect() expects a tcp::endpoint, and the endpoint type provided via udp::resolver::iterator is udp::endpoint. Attempting to directly use the result of the query from a different protocol will result in a compilation error:

boost::asio::io_service io_service;  
boost::asio::ip::tcp::socket socket(io_service);
boost::asio::ip::udp::resolver::iterator iterator = ...;
socket.connect(iterator->endpoint());
// ~~~^~~~~~~ no matching function call to `tcp::socket::connect(udp::endpoint)`
//            no known conversion from `udp::endpoint` to `tcp::endpoint`

Neither tcp::resolver nor udp::resolver dictate the transport layer protocol the name resolution will use. The DNS client will use TCP when either it become necessary or it has been explicitly configured to use TCP.

On systems where service name resolution is supported, when performing service-name resolution with a descriptive service name, the type of resolver can affect the results. For example, in the IANA Service Name and Transport Protocol Port Number Registry:

  • the daytime service uses port 13 on UDP and TCP
  • the shell service uses port 514 only on TCP
  • the syslog service uses port 514 only on UDP

Hence, one can use tcp::resolver to resolver the daytime and shell service, but not syslog. On the other hand, udp::resolver can resolve daytime and syslog, but not shell. The following example demonstrates this distinction:

#include <boost/asio.hpp>

int main()
{
  boost::asio::io_service io_service;

  using tcp = boost::asio::ip::tcp;
  using udp = boost::asio::ip::udp;

  boost::system::error_code error;
  tcp::resolver tcp_resolver(io_service);
  udp::resolver udp_resolver(io_service);

  // daytime is 13/tcp and 13/udp
  tcp_resolver.resolve(tcp::resolver::query("daytime"), error);
  assert(!error);
  udp_resolver.resolve(udp::resolver::query("daytime"), error);
  assert(!error);

  // shell is 514/tcp
  tcp_resolver.resolve(tcp::resolver::query("shell"), error);
  assert(!error);
  udp_resolver.resolve(udp::resolver::query("shell"), error);
  assert(error);

  // syslog is 514/udp
  tcp_resolver.resolve(tcp::resolver::query("syslog"), error);
  assert(error);
  udp_resolver.resolve(udp::resolver::query("syslog"), error);
  assert(!error);

  tcp_resolver.resolve(tcp::resolver::query("514"), error);
  assert(!error);
  udp_resolver.resolve(udp::resolver::query("514"), error);
  assert(!error);
}
like image 158
Tanner Sansbury Avatar answered Sep 22 '22 16:09

Tanner Sansbury