C++ IPv6多播在LAN中不工作

C++ IPv6多播在LAN中不工作,c++,networking,ipv6,multicast,C++,Networking,Ipv6,Multicast,我试图通过网络发送IPv6多播数据包。发送似乎有效,因为它到达了目标PC——至少它出现在WireShark中记录的网络流量中。但是它没有到达我的服务器程序。当我从应该接收数据包的同一台PC发送数据包时,它确实可以工作 这是用于发送的代码(删除了错误检查以提高可读性): 这是接收数据包的代码(删除错误检查以提高可读性): std::vector GetNetworkInterfaceIndicates(){ std::向量结果; /*声明和初始化变量*/ DWORD dwSize=0; DWORD

我试图通过网络发送IPv6多播数据包。发送似乎有效,因为它到达了目标PC——至少它出现在WireShark中记录的网络流量中。但是它没有到达我的服务器程序。当我从应该接收数据包的同一台PC发送数据包时,它确实可以工作

这是用于发送的代码(删除了错误检查以提高可读性):

这是接收数据包的代码(删除错误检查以提高可读性):

std::vector GetNetworkInterfaceIndicates(){
std::向量结果;
/*声明和初始化变量*/
DWORD dwSize=0;
DWORD dwRetVal=0;
无符号整数i=0;
//设置要传递给GetAdapterAddresses的标志
ULONG flags=GAA_FLAG_包括_前缀;
//默认为未指定的地址族(两个)
ULONG家族=AF_Unsec;
LPVOID lpMsgBuf=NULL;
PIP_适配器_地址paddress=NULL;
ULONG-exputflen=0;
ULONG迭代次数=0;
PIP_适配器_地址pCurrAddresses=NULL;
PIP_适配器_单播_地址pUnicast=NULL;
PIP_适配器_ANYCAST_地址pAnycast=NULL;
PIP_适配器_多播_地址pMulticast=NULL;
IP_适配器_DNS_服务器_地址*pDnServer=NULL;
IP_适配器_前缀*pPrefix=NULL;
族=AF_INET6;
//首先分配一个15 KB的缓冲区。
exputflen=工作缓冲区大小;
做{
paddress=(IP_适配器_地址*)MALLOC(exputflen);
if(paddress==NULL){
返回{0};
}
德维特瓦尔=
GetAdapterAddresses(族、标志、NULL、填充和扩展);
if(dwRetVal==错误\缓冲区\溢出){
免费(软垫);
paddress=NULL;
}
否则{
打破
}
迭代++;
}而((dwRetVal==ERROR_BUFFER_OVERFLOW)&(迭代次数IfIndex);
pCurrAddresses=pCurrAddresses->Next;
}
}
否则{
返回{0};
}
如果(软垫){
免费(软垫);
}
返回结果;
}
UDPSocket=套接字(AF_INET6、SOCK_DGRAM、IPPROTO_UDP);
sockaddr_in 6 UDP_Sock_in;
memset(&UDP_-Sock_-in,0,sizeof(sockaddr_-in 6));
UDP\u Sock\u in.sin6\u addr=in6addr\u any;
UDP_Sock_in.sin6_port=htons(设置::GetPort()+1);
UDP_Sock_in.sin6_family=PF_INET6;
setsockopt(UDPSocket、IPPROTO_IPV6、IPV6_v6)(char*)和No、sizeof(BOOL));
绑定(UDPSocket,(sockaddr*)和UDP_-Sock_-in,sizeof(UDP_-Sock_-in));
ipv6_mreq广播组;
memset(&BroadcastGroup,0,sizeof(ipv6_mreq));
const auto-IfIndices=GetNetworkInterfaceIndices();
BroadcastGroup.ipv6mr_multiaddr.u.Byte[0]=0xFF;
BroadcastGroup.ipv6mr_multiaddr.u.Byte[1]=0x18;
BroadcastGroup.ipv6mr_multiaddr.u.Byte[14]=0x12;
BroadcastGroup.ipv6mr_multiaddr.u.Byte[15]=0x43;
用于(常数自动和索引:IfIndices){
BroadcastGroup.ipv6mr_接口=索引;
setsockopt(UDPSocket、IPPROTO_IPV6、IPV6_添加_成员资格(char*)和BroadcastGroup、sizeof(IPV6_mreq));
} 
socklen\u t fromLength=sizeof(sockaddr\u in6);
pollfd pollfd;
PollFd.events=POLLIN;
PollFd.fd=UDPSocket;
PollFd.revents=-1;
WSAPoll(和PollFd,1,-1);
recvfrom(UDPSocket,(char*)缓冲区,MAXBUF,0,(sockaddr*)和from,以及fromLength);

我基本上尝试过指定每个网络接口索引,但数据包仍然没有到达服务器。我不知道会出什么问题。当发送方和接收方在同一台PC上时,为什么它能工作?我不明白。有人有主意吗?这不是防火墙,我把它关掉了,什么也没变。当我直接指定接收PC的IP地址时,它也能工作。

我找到了一个解决方法:只需切换到IPv4,因为IPv6多播目前似乎在Windows上不起作用(至少在我的使用案例中,请参阅注释)。我的代码已经工作了,但不久前就停止了工作,直到再次测试时我才注意到

我尝试了很多不同的地址,显然没有一个能在3种不同的设备上工作。然后我切换到IPv4,这很简单——我只将与IPv6相关的内容更改为与IPv4等效的内容,并删除了发送方上的跃点和接口选项


我的接收器甚至出现在多播组列表中(您可以使用命令“netsh interface ipv6 show joins”看到),但仍然没有收到发送到其地址的数据包,因此我断定这可能是一个bug,因为我找到的每一个示例代码都不适用于我,我也找不到任何其他可能遗漏的setsockopt选项。如果你知道什么可能导致这个问题,或者如何修复它,不需要切换到旧的IPv4标准,请自由评论。< /P> C或C++?请不要标记这两种语言,除非您实际上同时使用这两种语言编程。毕竟,它们是非常不同的语言。请检查您正在使用的函数的返回状态。毫无疑问,我猜不出问题是什么。它是C++,我改变了它,对不起。实际上,我检查了返回值,我只是在这篇文章中删除了它以提高可读性。根据我的经验,如果为每个网络接口创建一个单独的套接字,而不是尝试使用单个套接字处理所有网络接口,IPv6多播的效果会更好。(当然,这样做很痛苦)好吧,即使我只在一个接口上添加套接字,它也根本不起作用。我已经试过了,还有很多其他的选择。出于某种原因,它与IPv4一起工作时根本没有任何问题。我仍然想知道我是否做错了什么,或者它实际上是一个bug,但我想我永远也找不到。“IPv6多播目前似乎在Windows上不起作用”IPv6没有广播,所以它大量使用多播。视窗c
UDPBroadcastSocket = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
BOOL Yes = 1;
setsockopt(UDPBroadcastSocket, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&Yes, sizeof(BOOL));
int32_t hops = 50;
setsockopt(UDPBroadcastSocket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char*)&hops, sizeof(hops));
uint32_t IF = 0;
setsockopt(UDPBroadcastSocket, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char*)&IF, sizeof(IF));

struct sockaddr_in6 sock_in;
struct addrinfo *result = NULL;
struct addrinfo hints;

memset(&hints, 0, sizeof(hints));

hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
hints.ai_flags = AI_NUMERICHOST;

getaddrinfo("FF18::1243", "12346", &hints, &result);

unsigned char buffer[MAXBUF];
int PacketSize = 8;
int sinlen = int(result->ai_addrlen);
memcpy(&sock_in, result->ai_addr, result->ai_addrlen);

freeaddrinfo(result);

sendto(UDPBroadcastSocket, (char*)buffer, PacketSize, 0, (sockaddr *)&sock_in, sinlen);
std::vector<uint32_t> GetNetworkInterfaceIndices(){
    std::vector<uint32_t> Result;

    /* Declare and initialize variables */

    DWORD dwSize = 0;
    DWORD dwRetVal = 0;

    unsigned int i = 0;

    // Set the flags to pass to GetAdaptersAddresses
    ULONG flags = GAA_FLAG_INCLUDE_PREFIX;

    // default to unspecified address family (both)
    ULONG family = AF_UNSPEC;

    LPVOID lpMsgBuf = NULL;

    PIP_ADAPTER_ADDRESSES pAddresses = NULL;
    ULONG outBufLen = 0;
    ULONG Iterations = 0;

    PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
    PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
    PIP_ADAPTER_ANYCAST_ADDRESS pAnycast = NULL;
    PIP_ADAPTER_MULTICAST_ADDRESS pMulticast = NULL;
    IP_ADAPTER_DNS_SERVER_ADDRESS *pDnServer = NULL;
    IP_ADAPTER_PREFIX *pPrefix = NULL;



    family = AF_INET6;



    // Allocate a 15 KB buffer to start with.
    outBufLen = WORKING_BUFFER_SIZE;

    do {

        pAddresses = (IP_ADAPTER_ADDRESSES *)MALLOC(outBufLen);
        if (pAddresses == NULL) {
            return{ 0 };
        }

        dwRetVal =
            GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);

        if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
            FREE(pAddresses);
            pAddresses = NULL;
        }
        else {
            break;
        }

        Iterations++;

    } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (Iterations < MAX_TRIES));

    if (dwRetVal == NO_ERROR) {
        // If successful, output some information from the data we received
        pCurrAddresses = pAddresses;
        while (pCurrAddresses) {

            Result.emplace_back(pCurrAddresses->IfIndex);

            pCurrAddresses = pCurrAddresses->Next;
        }
    }
    else {

        return{ 0 };
    }

    if (pAddresses) {
        FREE(pAddresses);
    }

    return Result;
}



UDPSocket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);

sockaddr_in6 UDP_Sock_in;
memset(&UDP_Sock_in, 0, sizeof(sockaddr_in6));
UDP_Sock_in.sin6_addr = in6addr_any;
UDP_Sock_in.sin6_port = htons(Settings::GetPort()+1);
UDP_Sock_in.sin6_family = PF_INET6;

setsockopt(UDPSocket, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&No, sizeof(BOOL));

bind(UDPSocket, (sockaddr*)&UDP_Sock_in, sizeof(UDP_Sock_in));

ipv6_mreq BroadcastGroup;

memset(&BroadcastGroup, 0, sizeof(ipv6_mreq));

const auto IfIndices = GetNetworkInterfaceIndices();

BroadcastGroup.ipv6mr_multiaddr.u.Byte[0] = 0xFF;
BroadcastGroup.ipv6mr_multiaddr.u.Byte[1] = 0x18;
BroadcastGroup.ipv6mr_multiaddr.u.Byte[14] = 0x12;
BroadcastGroup.ipv6mr_multiaddr.u.Byte[15] = 0x43;

for (const auto& Index : IfIndices) {
    BroadcastGroup.ipv6mr_interface = Index;
    setsockopt(UDPSocket, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char*)&BroadcastGroup, sizeof(ipv6_mreq));        
} 



socklen_t fromLength = sizeof(sockaddr_in6);

pollfd PollFd;
PollFd.events = POLLIN;
PollFd.fd = UDPSocket;
PollFd.revents = -1;

WSAPoll(&PollFd, 1, -1);

recvfrom(UDPSocket, (char*)buffer, MAXBUF, 0, (sockaddr*)&from, &fromLength);