これは、 IPv4 クライアントを IPv6 サーバーに接続する: 接続が拒否されました の続きです。私はデュアル スタック ソケットを試しており、IPV6_V6ONLY を使用した setsockopt が何に役立つかを理解しようとしています。リンクされた質問で、「サーバーをIPv6にマップされたIPv4アドレスにもバインドする場合、IPV6_V6ONLYを0に設定すると便利です」とアドバイスされました。以下でこれを行い、サーバーがIPv6クライアントとIPv4クライアントの両方からの接続を受け入れることができることを期待していました. しかし、驚いたことに、クライアントを V4 および V6 ソケットで実行すると、どちらも接続できません!
誰かが私が間違っていることを教えてもらえますか、またはIPv6デュアルスタック機能をすべて誤解していますか?
サーバ:
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");
クライアント:
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);