SSDP и IP-адрес интерфейса - PullRequest
3 голосов
/ 04 марта 2011

Я пишу UPnP AV / DLNA DMS , который должен отправлять и получать SSDP сообщения.В ответ на некоторые M-SEARCH пакеты мне нужно отправить ответ с URL ресурса (в данном случае HTTP-сервера), который я выбрал для привязки к INADDR_ANY (0.0.0.0).Конечно, этот адрес не имеет смысла для отправителя пакета M-SEARCH: адрес интерфейса, на котором был получен M-SEARCH, является наиболее подходящим.

Как определить соответствующий адрес дляотправить в ответном пакете?

Некоторые идеи, которые я рассмотрел:

  1. Привязка отдельного получателя к каждому сокету.Когда получатель получает пакет M-SEARCH, адрес ответа может использовать локальный адрес сокета в ответе.Однако для этого необходимо знать и выполнять итерацию по всем интерфейсам, а также добавлять и удалять приемники при изменении доступности интерфейса.
  2. Установите один приемник на INADDR_ANY и выполните итерации масок интерфейса для определения возможного источника.Однако несколько интерфейсов могут использовать одну подсеть.
  3. Извлекать целевой IP-адрес пакета при его получении.Это зависит от IP-адреса и может быть потеряно где-то в сетевой абстракции.

1 Ответ

2 голосов
/ 04 марта 2011

getsockname(2), за которым следует getnameinfo(3), сообщает IP-адрес, который ваш стек TCP / IP назначил сокету.(Очевидно, что это не будет соответствовать тому, что клиент мог бы использовать, если сервер и клиент находятся на противоположных сторонах системы NAT; в этом случае, возможно, существует хитрая хитрость UPnP для обнаружения IP-адреса, который клиент может использовать для связи с сервером..)

Я предполагаю, что ваш сервер выглядит примерно так:

lfd = socket();
ret = bind(lfd,...);
connection = listen(lfd, 10);
/* add connection to your select queue or poll queue */

Вы можете добавить код, подобный следующему:

struct sockaddr_storage me;
socklen_t *len = sizeof(me);
char name[40];
ret = getsockname(connection, &me, &len);
ret = getnameinfo(&me, &len, name, sizeof(name), NULL, 0, NI_NUMERICHOST);

getnameinfo(3) проверяет struct sockaddr_storage me для вашего IP-адреса.Поскольку это общие интерфейсы, он будет работать для адресов IPv4 или IPv6.

...