Подключение клиента IPv4 к серверу IPv6: соединение отказано

Я экспериментирую с сокетами IPv6, особеннодвойной стек " возможность, предлагаемая в Windows Vista и более поздних версиях и, по-видимому, в Unix по умолчанию. Я обнаружил, что когда я привязываю свой сервер к определенному IP-адресу или к разрешению имени хоста моей локальной машины, я не могу принять соединение от клиента IPv4. Когда я связываюсь с INADDR_ANY, я могу.

Пожалуйста, рассмотрите следующий код для моего сервера. Вы можете видеть, что я следую за Microsoft 'Совет по созданию сокета IPv6 с установкой флага IPV6_V6ONLY на ноль:

addrinfo* result, *pCurrent, hints;

memset(&hints, 0, sizeof hints);    // Must do this!
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;     // We intend to use the addrinfo in a call to connect().  (I know it is ignored if we specify a server to connect to...)

int nRet = getaddrinfo("powerhouse", "82", &hints, &result);

SOCKET sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);

int no = 0;
if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&no, sizeof(no)) != 0)
    return -1;

if (bind(sock, result->ai_addr, result->ai_addrlen) ==  SOCKET_ERROR)
    return -1;

if (listen(sock, SOMAXCONN) == SOCKET_ERROR)
    return -1;

SOCKET sockClient = accept(sock, NULL, NULL);

Вот код для моего клиента. Вы видите, что я создаю сокет IPv4 и пытаюсь подключиться к своему серверу:

addrinfo* result, *pCurrent, hints;

memset(&hints, 0, sizeof hints);    // Must do this!
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;

if (getaddrinfo("powerhouse", "82", &hints, &result) != 0)
    return -1;

SOCKET sock = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
int nRet = connect(sock, result->ai_addr, result->ai_addrlen);

Результат моего соединения всегда 10061: соединение отказано.

Если я изменяю свой серверный код для привязки к :: (или передаю NULL-хост в getaddrinfo () (то же самое)), и изменяю свой клиентский код, чтобы указать NULL-хост в вызове getaddrinfo (), тогда клиент V4 может подключиться хорошо.

Кто-нибудь может объяснить, почему, пожалуйста? Я не читал ничего, что мы должны указать NULL-хост (следовательно, использовать INADDR_ANY), если мы хотим поведение с двумя сокетами. Это может'не является обязательным требованием, потому что у меня есть многосетевой хост, и я хочу принимать IPv4 только на некоторых доступных IP-адресах?

ИЗМЕНИТЬ 15/05/2013:

Это соответствующая документация, которая запутала меня, почему мой код не работает:

ОтРозетки с двумя стеками для приложений Winsock для IPv6 "

Windows Vista и более поздние версии предлагают возможность создания одного сокета IPv6, который может обрабатывать как трафик IPv6, так и трафик IPv4. Например, прослушивающий сокет TCP для IPv6 создается, переводится в режим двойного стека и привязывается к порту 5001. Этот сокет двойного стека может принимать подключения от TCP-клиентов IPv6, подключающихся к порту 5001, и от TCP-клиентов IPv4, подключающихся к порту 5001. «»

По умолчанию сокет IPv6, созданный в Windows Vista и более поздних версиях, работает только по протоколу IPv6. Чтобы превратить сокет IPv6 в сокет с двумя стеками, необходимо вызвать функцию setsockopt с опцией сокета IPV6_V6ONLY, чтобы установить это значение на ноль, прежде чем сокет будет привязан к IP-адресу.Когда параметр сокета IPV6_V6ONLY установлен на ноль, сокет, созданный для семейства адресов AF_INET6, может использоваться для отправки и получения пакетов с адреса IPv6 или с адреса сопоставления IPv4. (выделение мое)

Ответы на вопрос(2)

Ваш ответ на вопрос