Сетевое программирование IPv6 без IPv6?
Итак, я начал заниматься программированием сокетов, я одновременно пытаюсь научиться делать что-то, используя стандартную реализацию BSD, а также как это переводится в Winsock API в Windows. Я сам настраиваю заголовок библиотеки утилит Winsock, который может быть включен в будущие проекты, включающие сетевое взаимодействие. Я хочу, чтобы моя библиотека была независимой от IPv4/6 в том смысле, что в ней есть функции, которые работают как с IPv4, так и с IPv6.
Проблема, с которой я сталкиваюсь, заключается в том, что у меня нет доступа к интернет-сервису, очевидно, я не могу подключиться к интернету IPv6. Я знаю, что Всемирный день IPv6 приближается в июне, так что, возможно, это изменится. Хотя я в этом сомневаюсь. Во всяком случае, я не могу протестировать ни одну из написанных мной функций, особенно работающих на IPv6-адресах или хостах.
Вот пример:
У меня есть эта функция, которая должна принимать имя хоста в виде строки, разрешать его и затем возвращать презентабельный IP-адрес в виде строки. У меня есть версия [ip_string()], которая возвращает первый хороший IP-адрес, который он может получить в семействе адресов AF_INET или AF_INET6. Вторая версия [ip4_string()] будет возвращать только IPv6-адрес и то же самое с [ip6_string()], возвращающим IPv6-адрес.
char *ip_string(const char hostname[])
{
char *buffer = new char[INET6_ADDRSTRLEN];
struct addrinfo hints, *res, *ptr;
void *addr = NULL; // void pointer to be set to sin_addr or sin6_addr
/** Initialize hints structure */
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC; // ipv4 or ipv6 address family
hints.ai_socktype = SOCK_STREAM;
/** Function getaddrinfo returns non-zero if there's a problem */
if (getaddrinfo(hostname, "http", &hints, &res) != 0)
throw WinsockException("getaddrinfo()");
/** Loop through list of address structures till we find a valid IP */
const int MAX_ATTEMPTS = 15;
int i = 0;
for (ptr = res; (ptr != NULL); ptr = ptr->ai_next)
{
if (i++ <= MAX_ATTEMPTS)
{
if (ptr->ai_family == AF_INET)
{ // Cast appropriately for ipv4
addr = &(((struct sockaddr_in *)ptr->ai_addr)->sin_addr);
inet_ntop(ptr->ai_family, (in_addr*) addr, buffer, INET_ADDRSTRLEN);
}
else if (ptr->ai_family == AF_INET6)
{ // Cast appropraitely for ipv6
addr = &(((struct sockaddr_in6 *)ptr->ai_addr)->sin6_addr);
inet_ntop(ptr->ai_family, (in6_addr*) addr, buffer, INET6_ADDRSTRLEN);
}
}
}
freeaddrinfo(res); // free list of address structures
if (addr == NULL)
{
delete [] buffer;
return NULL;
}
return buffer;
}
Проблема у меня заключается в том (я предполагаю), потому что я не на соединении, которое может достичь адресного пространства IPv6 (что я подтвердил http://test-ipv6.com/), всякий раз, когда любая из этих функций вызывает getaddrinfo() на на хосте ipv6 функция, кажется, вообще не возвращается.
Это нормально? Есть ли способ проверить соединение, чтобы узнать, включен ли ipv6 через Winsock API? Есть ли какой-нибудь хороший способ проверить код с поддержкой ipv6 на подключении, отличном от ipv6?
2 ответа
Вы можете настроить свою собственную маленькую объединенную сеть IPv6, чтобы проверить это, но вам будет гораздо проще получить себе туннель IPv6.
Даже если ваш провайдер не предлагает доступ к IPv6 (вы должны кричать на них за это!), Вы все равно можете получить пригодное для использования соединение IPv6. Посмотрите на Hurricane Electric, например.
Ваша непосредственная проблема может быть такой же простой, как то, что сказала Кароли. Просто избавьтесь от первого оператора if() внутри цикла for. В любом случае это избыточно (кроме того, что дополнительный i++ ломает вещи!).
Чтобы ответить на ваш вопрос о проверке доступности IPv6, вы можете использовать WSAEnumProtocols()
чтобы узнать, установлена ли в ОС IPv6, но это покажет вам, сможете ли вы использовать в коде сокеты и функции IPv6, а не сможете ли вы устанавливать соединения IPv6 по сети. Если ваша сеть не поддерживает IPv6, вы ничего не можете сделать. Я бы посоветовал вам приобрести маршрутизатор с поддержкой IPv6 и создать частную локальную сеть для тестирования.