我尝试通过网络发送IPv6组播数据包。发送似乎有效,因为它到达目标PC - 至少它出现在WireShark中记录的网络流量中。但它没有到达我的服务器程序。当我从应该接收它的同一台PC发送数据包时,它确实可以工作。
这是发送代码(删除错误检查以提高可读性):
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);
我基本上尝试指定每个网络接口索引,但数据包仍未到达服务器。我不知道会出现什么问题。当发送者和接收者在同一台PC上时,为什么它可以工作?我不明白这一点。有没有人有想法?它不是防火墙,我把它关掉了,没有任何改变。当我直接指定接收PC的IP地址时,它也可以正常工作。
答案 0 :(得分:-2)
我找到了一种解决方法:只需切换到IPv4,因为IPv6多播目前似乎无法在Windows上运行(至少在我的用例中,请参阅注释)。我的代码已经运行了,但是前一段时间停止工作,直到我再次测试它才发现。
我尝试了一堆不同的地址,显然它们都没有在3种不同的设备上运行。然后我切换到IPv4,它只是工作 - 我只将IPv6相关的东西改为他们的IPv4等价物,并删除了发送者的跳跃和界面选项。
我的接收器甚至出现在多播组列表中(您可以使用命令&#34; netsh interface ipv6 show joins&#34;)看到,但仍然没有收到发送到其地址的数据包,所以我得出结论,它可能是一个错误,因为我找到的每个示例代码都不适合我,我找不到任何其他我可能错过的setsockopt选项。如果您知道可能导致此问题的原因或如何修复它而不切换回旧的IPv4标准,请随时发表评论。