connect() возвращает "неверный аргумент" с адресом ipv6
У меня есть эта простая пара клиент-серверных приложений. Код довольно прост, я использую только новые рекомендованные методы, такие как getaddinfo и т. Д., И все отлично работает для ipv4. Даже для петли ipv6 (::1) это работает. Проблемы начинаются, когда дело доходит до некоторых других адресов ipv6... У меня есть две машины в сети, все работает нормально, когда я передаю их адреса ipv4, но когда я даю свой клиентский адрес ipv6, я получаю сообщение об ошибке при соединении: неверный аргумент, Эй, разве я уже не знаю это? Я делаю! Когда я пытаюсь ping6 этот IPv6- адрес, я получаю ту же ошибку:
connect: неверный аргумент
Но есть способ преодолеть этот блок - нужно выбрать интерфейс с ключом -I, и с тех пор все работает без сбоев. Но как я могу добиться того же в моем клиентском приложении? Что я должен делать? Мой клиентский код выглядит так:
struct addrinfo hints;
struct addrinfo *server;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
int status;
if((status = getaddrinfo(argv[1], argv[2], &hints, &server) != 0))
{
perror("getaddrinfo error");
return 1;
}
int sock_fd;
struct addrinfo *ptr;
for(ptr=server;ptr!=NULL;ptr=ptr->ai_next)
{
if( (sock_fd = socket(ptr->ai_family,ptr->ai_socktype,ptr->ai_protocol)) == -1)
{
perror("socket error");
continue;
}
if( connect(sock_fd, ptr->ai_addr,ptr->ai_addrlen) == -1 )
{
perror("connect error");
continue;
}
break;
}
3 ответа
Адреса, начинающиеся с ff...
многоадресные адреса. Подключение потока к многоадресному адресу не работает.
Адреса, начинающиеся с fe80...
являются локальными ссылочными адресами, с которыми связан идентификатор интерфейса. Попробуйте посмотреть на sockaddr
вернулся из getaddrinfo
, это scope
поле заполнено?
Вам нужно указать интерфейс для пинга IPv6 (т.е. -I eth0):
ping6 -I eth0 fe80::208:54ff:fe34:22ae
При использовании локальных адресов канала для проверки связи IPv6 требуется определить, какое устройство должно отправлять / получать пакет - каждое устройство имеет локальный адрес канала.
Попытка без этого приведет к сообщению об ошибке, например:
--> # ping6 fe80::208:54ff:fe34:22ae
connect: Invalid argument
В этом случае вы должны указать интерфейс, как показано здесь:
--> # ping6 -I eth0 fe80::208:54ff:fe34:22ae
PING fe80::208:54ff:fe34:22ae(fe80::208:54ff:fe34:22ae) from fe80::208:54ff:fe34:22ae eth0: 56 data bytes
64 bytes from fe80::208:54ff:fe34:22ae: icmp_seq=0 ttl=64 time=0.027 ms
64 bytes from fe80::208:54ff:fe34:22ae: icmp_seq=1 ttl=64 time=0.030 ms
64 bytes from fe80::208:54ff:fe34:22ae: icmp_seq=2 ttl=64 time=0.036 ms
Один подобный подход вы должны следовать в своем клиентском приложении.
Я рекомендую вам включить протокол IP6 в интерфейсе / сетевом соединении, кроме того, выкиньте протокол ip4, если у вас все еще есть ошибка.
На моем Linux Box это также происходило, когда у меня был активен ip4-интерфейс, и мое приложение пыталось использовать ip4-интерфейс с настройками ip6. То же самое должно быть действительно для окон.
Если что-то не понятно спросите.