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);