Подписка на несколько групп многоадресной рассылки на одном сокете (Linux, C) - PullRequest
7 голосов
/ 11 февраля 2012

Можно ли получать данные из нескольких групп многоадресной рассылки по одному сокету?

Например:

void AddGroup(int sock,
              const char* mc_addr_str,
              int mc_port,
              const char* interface) {
  struct sockaddr_in mc_addr;
  memset(&mc_addr, 0, sizeof(mc_addr));
  mc_addr.sin_family      = AF_INET;
  mc_addr.sin_addr.s_addr = inet_addr(mc_addr_str);
  mc_addr.sin_port        = htons(mc_port);

  if ((bind(sock, (struct sockaddr *) &mc_addr,
            sizeof(mc_addr))) < 0) {
    perror("bind() failed");
    exit(1);
  }

  // construct an IGMP join request structure
  struct ip_mreq mc_req;
  mc_req.imr_multiaddr.s_addr = inet_addr(mc_addr_str);
  mc_req.imr_interface.s_addr = inet_addr(interface);

  if ((setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                  (void*) &mc_req, sizeof(mc_req))) < 0) {
    perror("setsockopt() failed");
    exit(1);
  }
}

Этот код работает, когда я добавляю одну многоадресную группу. Но когда я пытаюсь добавить еще один, «привязка» не удается. Я не совсем понимаю, почему связь должна быть там во-первых? (но код не работает без него).

В идеале я хотел бы вызывать AddGroup несколько раз в одном сокете. Это возможно? Или мне нужен один сокет на группу, а затем просто использовать опрос?

Ответы [ 6 ]

6 голосов
/ 13 февраля 2012

Вы можете присоединиться к столько групп многоадресной рассылки, сколько захотите, используя соответствующий вызов setsockopt() с параметром IP_ADD_MEMBERSHIP вместо bind ().

3 голосов
/ 11 февраля 2012

Вы связываете сокет только один раз. Пропустите привязку во второй раз и посмотрите, что произойдет.

2 голосов
/ 28 апреля 2012

Вы можете объединить столько групп многоадресной рассылки, сколько хотите, в одном сокете. См. Setsockopt (), IP_PKTINFO, чтобы узнать, из какой многоадресной группы вы читаете данные.

2 голосов
/ 19 февраля 2012

bind на пассивный адрес, то есть 0.0.0.0 для IPv4, и используйте ASM или SSM для добавления дополнительных групп, например, IP_ADD_MEMBERSHIP как указано.

Вы можете только bind один раз.

0 голосов
/ 15 марта 2014

Да, это возможно: посмотрите пример в ссылке (http://www.tenouk.com/Module41c.html) Чтобы сократить это в несколько шагов:

  1. Вы устанавливаете с SO_REUSEADDR
  2. Вы связываетесь с INADDR_ANY
  3. Вы устанавливаете опцию IP_ADD_MEMBERSHIP для каждой группы, из которой хотите получать дейтаграмму.
  4. Мне кажется, что использование IP_PKTINFO дает возможность различать полученные пакеты, но отправитель должен позаботиться о подготовке их ( Настройка исходного IP-адреса для сокета UDP )
0 голосов
/ 11 февраля 2012

Я не верю, что возможно присоединиться к нескольким группам многоадресной рассылки в данном сокете. Сокет определяется сопряжением исходного IP / порта и целевого IP / порта. Операционная система не будет знать, что делать с данными, поступающими со второго ip / порта, потому что у нее не будет сокета для ее отправки.

Связывание необходимо для регистрации соединения с операционной системой. Это в основном как регистрация дескриптора файла.

Лучший способ сделать это - создать сокет для каждой многоадресной группы, а затем вызвать select (). select () сообщит вам, есть ли в любом сокете данные, готовые для чтения.

Проверьте справочные страницы для получения дополнительной информации о socket (), bind () и выберите ().

...