Разница между socket.connect и boost:: asio:: connect

Я использую boost :: asio для сетевого взаимодействия, и мне интересно, почему в примерах иногда используется socket.connect(endpoint) а в некоторых других случаях используется boost::asio::connect(socket, endpoint). Согласно коду, boost::asio::connect вызывает socket.connect в цикле для итераторов конечных точек. Итак, мой вопрос:

Какое поведение лучше? Используя boost :: asio :: connect или socket.connect? Лично я предпочитаю socket.connect, потому что у меня есть только одна конечная точка. Или я ошибаюсь и неправильно понял asio libs.

Также мой второй вопрос: почему конечная точка является итератором? Как это возможно, более одного соединения, когда дается 1 IP и 1 порт?

Также есть boost :: asio :: write и socket.write...

Примеры:

  1. boost :: asio :: connect (сокет, конечная точка) blocking_tcp_echo_client.cpp.
  2. Socket.connect (конечная точка) (немного старше, но все еще работает) Daytime.1

Ответ 1

boost::asio::connect() - это свободная функция более высокого уровня, которая будет вызывать boost::asio::ip::tcp::socket::connect(). Документация здесь довольно понятна.

Эта функция пытается подключить сокет к одной из последовательностей конечные точки. Он делает это путем повторных вызовов сокета connect функции-члена, один раз для каждой конечной точки в последовательности, пока соединение успешно установлено.

Ничто не имеет лучшего поведения, хотя это в значительной степени субъективный термин. Это зависит от вас и вашего приложения, как вы хотите управлять установлением соединения. Если вам нужно предоставить некоторую обратную связь пользователю, например: "attempting to connect to host 1 of 10", предпочтительнее использовать socket.connect() в цикле, а не в бесплатной функции connect().

Свободная функция connect() принимает итератор конечной точки, чтобы он мог подключаться ко всем возможным конечным точкам, которые разрешены. Этот echo-клиент tcp, с которым вы связались, делает это

tcp::resolver resolver(io_service);
tcp::resolver::query query(tcp::v4(), argv[1], argv[2]);
tcp::resolver::iterator iterator = resolver.resolve(query);

tcp::socket s(io_service);
boost::asio::connect(s, iterator);

Ответ 2

Почему конечная точка является итератором?

Запрос (tcp:: resolver:: query) с 1 ip и 1 портом имеет только одну конечную точку, но параметры запроса могут содержать URL:

boost::asio::ip::tcp::resolver::query query("www.baidu.com", "http");  

Запрос может получить несколько IP-адресов baidu.com, как показано на рисунке:

boost::asio::ip::tcp::resolver::query query1("www.baidu.com", "http");
boost::asio::ip::tcp::resolver::iterator iter = resolver.resolve(query1);
boost::asio::ip::tcp::resolver::iterator end; 
while (iter != end)
{
    boost::asio::ip::tcp::endpoint endpoint = *iter++;
    std::cout << endpoint << std::endl;
}

Вывод:

180.97.33.108:80
180.97.33.107:80

----------

В примере daytime.1:

tcp::resolver::query query(argv[1], "daytime");
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);

Теперь мы создаем и подключаем сокет. Список конечных точек, полученных выше, может содержать как конечные точки IPv4, так и IPv6, поэтому нам нужно попробовать каждый из них, пока мы не найдем тот, который работает. Таким образом, клиентская программа не зависит от конкретной версии IP.

Запрос может содержать несколько конечных точек, boost:: asio:: connect() может автоматически подключаться к нему.