Использование `sendto()` в сокете IPv6 для отправки на адрес IPv4

#sockets #portability #ipv6 #freebsd #ipv4

#сокеты #переносимость #ipv6 #freebsd #ipv4

Вопрос:

У меня есть приложение на C , которое использует тот же сокет UDP IPv6 для отправки адресатам IPv6 или IPv4.

 sockfd = socket(PF_INET6, SOCK_DGRAM, 0);
dest_addr.sin6_family = AF_INET;
dest_addr.sin6_port = htons(dest_port);
inet_pton ("192.168.1.33",  amp;dest_addr.sin6_addr);
sendto (sockfd, message, strlen(message) 1, 0, (struct sockaddr *)amp;dest_addr, sizeof(struct sockaddr_in6));
  

В Linux это работает нормально, но во FreeBSD я получаю ошибку Address family not supported by protocol family при отправке на адреса IPv4.

Есть ли способ настроить FreeBSD так, чтобы она принимала это? Может быть, аналогично ipv6_ipv4mapping="YES" для прослушивания клиентов IPv4?

Комментарии:

1. Не было бы лучше иметь сокет для ipv4 и один для ipv6?

2. @Paolo: По двум причинам: а.) это хорошо вписывается в существующую структуру программы (на основе IPv4) и б.) приложение уже использует много сотен сокетов, и я бы предпочел не удваивать его.

3. в C вам нужно только (sockaddr *) , а не (struct sockaddr *)

Ответ №1:

Вы создаете сокет IPv6, поэтому вы должны использовать адреса IPv6. Однако, если ваша ОС поддерживает сокеты с двумя стеками (т. Е. Изначально поддерживает как IPv4, так и IPv6 в одном сокете), тогда используйте IPv4-сопоставленный IPv6-адрес для отправки на адрес IPv4 (если ОС это позволяет, некоторые этого не делают). В противном случае вам придется использовать отдельные сокеты для IPv4 и IPv6.

Комментарии:

1. Linux, похоже, не видит этого таким образом, и код работает нормально. Я надеялся, что у FreeBSD будет переключатель, который будет немного более расслабленным.

2. @GeneVincent — Я не знаком с FreeBSD, но у меня сложилось впечатление, что изменение его на inet_pton("::ffff:192.168.1.33", amp;dest....); должно работать на FreeBSD

3. @awoodland: Уверен, что это работает, но это означает преобразование каждого адреса. Общесистемный переход на поведение Linux лучше соответствовал бы моим потребностям, но, я думаю, мне придется перейти на преобразование.

4. @GeneVincent — моим предложением было бы заменить вызовы на inet_pton вашей собственной функцией, которая может вставлять "::ffff:" по мере необходимости.