【发布时间】:2018-07-06 14:42:58
【问题描述】:
下面的代码无法加入 IP 组播组地址 0:0:0:0:0:ffff:efc0:202,即 IPv4 地址 239.192.2.2 转换为 IPv6。
故障发生在这里:
if (setsockopt(m_socket, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char*)&multicastRequest, sizeof(multicastRequest)) < 0)
{
int rc = WSAGetLastError();
printf("Failed to join multicast group. Error = %d\n", rc);
}
WSAGetLastError() 返回 10049(“请求的地址在其上下文中无效”),我觉得这很奇怪,因为双模式套接字应该能够从 IPv4 和 IPv6 地址接收 UDP 数据。
如果我尝试这样做:
if (setsockopt(m_socket, IPPROTO_IPV4, IP_ADD_MEMBERSHIP, (char*)&multicastRequest, sizeof(multicastRequest)) < 0)
{
int rc = WSAGetLastError();
printf("Failed to join multicast group. Error = %d\n", rc);
}
失败,错误代码 rc = 10022(“向 setsockopt 提供了无效参数”)
代码在 Windows 10 机器上的 MS Visual Studio 2015 中执行。
#define WIN32_LEAN_AND_MEAN
#include <string>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
void main(void)
{
std::string ip = "0:0:0:0:0:ffff:efc0:202";
WSADATA wsaData;
struct ipv6_mreq multicastRequest;
SOCKET m_socket;
int off = 0;
struct addrinfo* tmp = nullptr;
struct addrinfo hints = { 0 };
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return;
}
hints.ai_family = AF_INET6;
hints.ai_flags = AI_NUMERICHOST;
getaddrinfo(ip.c_str(), NULL, &hints, &tmp);
m_socket = socket(AF_INET6, SOCK_DGRAM, 0);
if (setsockopt(m_socket, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&off, sizeof(off)) < 0)
{
int rc = WSAGetLastError();
printf("Failed to set socket option IPV6_V6ONLY. Error = %d\n", rc);
}
memcpy(&multicastRequest.ipv6mr_multiaddr, &((struct sockaddr_in6*)(tmp->ai_addr))->sin6_addr, sizeof(multicastRequest.ipv6mr_multiaddr));
multicastRequest.ipv6mr_interface = 0;
if (setsockopt(m_socket, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char*)&multicastRequest, sizeof(multicastRequest)) < 0)
{
int rc = WSAGetLastError();
printf("Failed to join multicast group. Error = %d\n", rc);
}
if (setsockopt(m_socket, IPPROTO_IPV4, IP_ADD_MEMBERSHIP (char*)&multicastRequest, sizeof(multicastRequest)) < 0)
{
int rc = WSAGetLastError();
printf("Failed to join multicast group. Error = %d\n", rc);
}
}
【问题讨论】:
-
你是什么意思'失败与 10049'?如果发生错误,Setsockopt 返回 -1。是 ERRNO 值还是什么?
-
@SergeyA 对不起。是的,返回 10049 的是 WSAGetLastError()
-
您是否费心从 WinSock 中查找错误代码 10049 的实际含义?
-
因为您没有发布 MCVE(没有显示调用 WSAGetLastError 的代码),并且您没有在 Microsoft 文档网站上查看此错误代码的含义。
-
FWIW,我从未尝试过,但如果将 IPv4 映射的 IPv6 地址添加到 IPv6 多播组中甚至是合法的/可能的,我会感到非常惊讶。 IPv6 有自己特定的多播范围 (ff00::/8)
标签: c++ networking udp multicast