Хобрук: Ваш путь к мастерству в программировании

Почему вызов соединения UDP игнорирует многоадресный маршрут обратной петли, но работает sendto без соединения?

Я установил сокет UDP с тем же удаленным адресом в диапазоне многоадресной рассылки. Один отправляет на 224.2.0.6:6666, другой на 224.2.0.7:6666. Я полагаюсь на таблицу маршрутизации Linux, чтобы определить, через какой интерфейс отправлять пакеты.

В обоих случаях я устанавливаю сокет в начале, устанавливаю свои сокеты и делаю sendto(). Я не устанавливаю конкретный IP_MULTICAST_IF.

Однако в первом случае я также делаю connect() перед первым sendto().

В случае connect() ОС игнорирует петлевой маршрут и отправляет все пакеты через маршрут и интерфейс по умолчанию.

В случае, отличном от connect(), ОС учитывает петлевой маршрут, и все пакеты отправляются через петлевой интерфейс.

Почему socket()-connect()-sendto() с маршрутом через lo заставляет ОС игнорировать его, в то время как просто выполнение socket()-sendto() с маршрутом через lo маршрутизируется правильно?

My ip route:

224.2.0.0/16 via 127.0.0.1 dev lo
default via 172.16.5.1 dev eth0 

Обратите внимание, что эта проблема возникает только, если маршрут идет к петлевому интерфейсу. Если я устанавливаю маршрут через «настоящий» интерфейс — фактический, macvlan, фиктивный, что угодно, — тогда и connect(), и sendto() одинаково учитывают маршрут и работают нормально.

ОБНОВИТЬ:

Оригинальный код. Форматирование было перепутано, так как это была правка чужого кода, пытался почистить вручную, извиняюсь за беспорядок:

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <stdlib.h>

int fd, fd2;
struct in_addr interface_addr;
int addr_size;
int optval = 1, recv_len = 4;
char *remote_ip = "224.2.0.6", *remote_ip2 = "224.2.0.7";
char *remote_port = "6666";
char *buf = "conn", *buf2 = "send";
struct addrinfo *remote_address_info, *remote_address_info2;

int main() {
  // create first and second socket
  if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    perror("socket() failed");
  }
  if ((fd2 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    perror("socket2() failed");
  }

  // set socket options on both
  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval) < 0) {
    perror("setsockopt(SO_REUSEADDR) failed");
  }
  if (setsockopt(fd2, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval) < 0) {
    perror("setsockopt2(SO_REUSEADDR) failed");
  }

  addr_size = sizeof(interface_addr);

  // structure the addr
  if (getaddrinfo(remote_ip, remote_port, NULL, &remote_address_info) != 0) {
    perror("getaddrinfo(remote_ip) failed");
  }
  if (getaddrinfo(remote_ip2, remote_port, NULL, &remote_address_info2) != 0) {
    perror("getaddrinfo2(remote_ip) failed");
  }

  // connect ON FIRST SOCKET ONLY
  if (connect(fd, remote_address_info->ai_addr, remote_address_info->ai_addrlen) != 0) {
    perror("connect() failed");
  }

  // sendto first and second
  // same result if use send() or sendto() on first socket
  if (sendto(fd, buf, recv_len, 0, remote_address_info->ai_addr, remote_address_info->ai_addrlen) == -1) {
    perror("sendto() failed");
  }
  if (sendto(fd2, buf2, recv_len, 0, remote_address_info2->ai_addr, remote_address_info2->ai_addrlen) == -1) {
    perror("sendto2() failed");
  }
}
03.08.2015

  • Что такое UDP-соединение? 03.08.2015
  • Какой параметр в коннекте? 03.08.2015
  • connect имеет смысл для меня только в том случае, если за ним следует отправка. Подключение к сокету udp в основном означает, что вы всегда будете отправлять в одно и то же место назначения, и поведение аналогично sendto с использованием того же адреса, что и при подключении. см. stackoverflow.com/questions/9741392/ 03.08.2015
  • @PhilipStuyck, ты прав. Я всегда рассматривал это как удобный метод. sendto всегда требует адрес назначения и сокет fd. С connect я могу обойтись без адреса. Но явно он делает что-то дополнительное на уровне ОС. И такое же поведение происходит с send как sendto 03.08.2015
  • @AndrewHenle публикует сейчас.... 03.08.2015
  • @PhilipStuyck Или, если вы хотите получать только от этого сверстника. 04.08.2015
  • @EJP, хорошая мысль. В любом случае, я точно знаю поведение - connect() немедленно устанавливает сокет и игнорирует маршрут 224.2.0.0/8 via 127.0.0.1, отправляя по маршруту по умолчанию, в то время как сокет, который просто идет прямо к sendto(), всегда отправляет, используя маршрут. Но почему? 04.08.2015

Новые материалы

Учебные заметки JavaScript Object Oriented Labs
Вот моя седьмая неделя обучения программированию. После ruby ​​и его фреймворка rails я начал изучать самый популярный язык интерфейса — javascript. В отличие от ruby, javascript — это более..

Разбор строк запроса в vue.js
Иногда вам нужно получить данные из строк запроса, в этой статье показано, как это сделать. В жизни каждого дизайнера/разработчика наступает момент, когда им необходимо беспрепятственно..

Предсказание моей следующей любимой книги 📚 Благодаря данным Goodreads и машинному обучению 👨‍💻
«Если вы не любите читать, значит, вы не нашли нужную книгу». - J.K. Роулинг Эта статья сильно отличается от тех, к которым вы, возможно, привыкли . Мне очень понравилось поработать над..

Основы принципов S.O.L.I.D, Javascript, Git и NoSQL
каковы принципы S.O.L.I.D? Принципы SOLID призваны помочь разработчикам создавать надежные, удобные в сопровождении приложения. мы видим пять ключевых принципов. Принципы SOLID были разработаны..

Как настроить Selenium в проекте Angular
Угловой | Селен Как настроить Selenium в проекте Angular Держите свое приложение Angular и тесты Selenium в одной рабочей области и запускайте их с помощью Mocha. В этой статье мы..

Аргументы прогрессивного улучшения почти всегда упускают суть
В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

Введение в Джанго Фреймворк
Схема «работать умно, а не усердно» В этой и последующих статьях я познакомлю вас с тем, что такое фреймворк Django и как создать свое первое приложение с помощью простых и понятных шагов, а..