Użyj gniazd IN6ADDR_SETV4MAPPED i podwójnego stosu

To jest kontynuacjaPodłączanie klienta IPv4 do serwera IPv6: odrzucono połączenie. Eksperymentuję z gniazdami z dwoma stosami i próbuję zrozumieć, do czego jest przydatny zestaw setsockopt z IPV6_V6ONLY. W powiązanym pytaniu poinformowano mnie, że „Ustawienie IPV6_V6ONLY na 0 może być przydatne, jeśli serwer jest również powiązany z adresem IPv4 mapowanym na IPv6”. Zrobiłem to poniżej i spodziewałem się, że mój serwer będzie mógł akceptować połączenia zarówno od klienta IPv6, jak i IPv4. Ale szokująco, kiedy uruchamiam klienta z gniazdem V4 i V6, żadne z nich nie może się połączyć!

Czy ktoś może mi powiedzieć, co robię źle, czy też źle zrozumiałem funkcję podwójnego stosu IPv6?

Serwer:

void ConvertToV4MappedAddressIfNeeded(PSOCKADDR pAddr)
{
// if v4 address, convert to v4 mapped v6 address
if (AF_INET == pAddr->sa_family)
{
    IN_ADDR In4addr;
    SCOPE_ID scope = INETADDR_SCOPE_ID(pAddr);
    USHORT port = INETADDR_PORT(pAddr);
    In4addr = *(IN_ADDR*)INETADDR_ADDRESS(pAddr);
    ZeroMemory(pAddr, sizeof(SOCKADDR_STORAGE));
    IN6ADDR_SETV4MAPPED(
        (PSOCKADDR_IN6)pAddr,
        &In4addr,
        scope,
        port
        );
    }
} 

addrinfo* result, hints;

memset(&hints, 0, sizeof hints); 
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;

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;

ConvertToV4MappedAddressIfNeeded(result->ai_addr);

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

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

SOCKET sockClient = accept(sock, NULL, NULL);
printf("Got one!\n");

Klient:

addrinfo* result, *pCurrent, hints;
char szIPAddress[INET6_ADDRSTRLEN];

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

const char* pszPort = "82";

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

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

questionAnswers(1)

yourAnswerToTheQuestion