gpt4 book ai didi

windows - 在多宿主 Windows PC 上接收多播消息

转载 作者:可可西里 更新时间:2023-11-01 10:09:42 25 4
gpt4 key购买 nike

我正在基于 multicast/udp 在具有多个网络接口(interface)的 PC 上开发诊断工具。用户可以选择一个 NIC,应用程序创建套接字,将它们绑定(bind)到这个 NIC 并将它们添加到特定的多播组。

多播消息的发送工作正常。但是,只有当我将套接字绑定(bind)到我 PC 的特定 NIC 时,消息接收才会成功。它几乎看起来像是在 Windows 中有一个用于接收多播消息的“默认”NIC,它始终是 GetAdapterInfo 函数返回的第一个 NIC。

我用 Wireshark 监控网络,发现“IGMP Join Group”消息不是从我绑定(bind)套接字的 NIC 发送的,而是由这个“默认”NIC 发送的。

如果我禁用此 NIC(或移除网线),GetAdapterInfo 返回的列表中的下一个 NIC 将用于接收多播消息。

我通过在我的 PC 的路由表中添加一个额外的条目成功地更改了这个“默认”NIC,但我认为这不是解决问题的好方法。

下面附加的代码也会出现此问题。加入组消息不是通过 192.168.52 发送的,而是通过不同的 NIC 发送的。

// socket_tst.cpp : Defines the entry point for the console application.
//

\#include tchar.h
\#include winsock2.h
\#include ws2ipdef.h
\#include IpHlpApi.h
\#include IpTypes.h

\#include stdio.h

int _tmain(int argc, _TCHAR* argv[])
{
WSADATA m_wsaData;
SOCKET m_socket;
sockaddr_in m_sockAdr;
UINT16 m_port = 319;
u_long m_interfaceAdr = inet_addr("192.168.1.52");
u_long m_multicastAdr = inet_addr("224.0.0.107");

int returnValue = WSAStartup(MAKEWORD(2,2), &m_wsaData);
if (returnValue != S_OK)
{
return returnValue;
}

// Create sockets
if (INVALID_SOCKET == (m_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) )
{
return WSAGetLastError();
}

int doreuseaddress = TRUE;
if (setsockopt(m_socket,SOL_SOCKET,SO_REUSEADDR,(char*) &doreuseaddress,sizeof(doreuseaddress)) == SOCKET_ERROR)
{
return WSAGetLastError();
}

// Configure socket addresses
memset(&m_sockAdr,0,sizeof(m_sockAdr));
m_sockAdr.sin_family = AF_INET;
m_sockAdr.sin_port = htons(m_port);
m_sockAdr.sin_addr.s_addr = m_interfaceAdr;

//bind sockets
if ( bind( m_socket, (SOCKADDR*) &m_sockAdr, sizeof(m_sockAdr) ) == SOCKET_ERROR )
{
return WSAGetLastError();
}

// join multicast
struct ip_mreq_source imr;

memset(&imr,0,sizeof(imr));
imr.imr_multiaddr.s_addr = m_multicastAdr; // address of multicastgroup
imr.imr_sourceaddr.s_addr = 0; // sourceaddress (not used)
imr.imr_interface.s_addr = m_interfaceAdr; // interface address
/* first join multicast group, then registerer selected interface as
* multicast sending interface */
if( setsockopt( m_socket
,IPPROTO_IP
,IP_ADD_MEMBERSHIP
,(char*) &imr
, sizeof(imr))
== SOCKET_ERROR)
{
return SOCKET_ERROR;
}
else
{
if( setsockopt(m_socket
,IPPROTO_IP
,IP_MULTICAST_IF
,(CHAR*)&imr.imr_interface.s_addr
,sizeof(&imr.imr_interface.s_addr))
== SOCKET_ERROR )
{
return SOCKET_ERROR;
}
}

printf("receiving msgs...\n");
while(1)
{
// get inputbuffer from socket
int sock_return = SOCKET_ERROR;
sockaddr_in socketAddress;
char buffer[1500];

int addressLength = sizeof(socketAddress);
sock_return = recvfrom(m_socket, (char*) &buffer, 1500, 0, (SOCKADDR*)&socketAddress, &addressLength );
if( sock_return == SOCKET_ERROR)
{
int wsa_error = WSAGetLastError();
return wsa_error;
}
else
{
printf("got message!\n");
}
}

return 0;
}

谢谢四位的帮助!

最佳答案

问题是一个简单的拼写错误。如果使用选项 IP_MULTICAST_IF,则必须使用结构 struct ip_mreq 而不是使用结构 struct ip_mreq_source。 (IP_ADD_SOURCE_MEMBERSHIP 选项需要其他结构)

使用错误的结构很可能会导致 setsockeopt 函数在预期的 NIC IP 地址处找到一个零。零也是 INADDR_ANY 常量的值,它选择系统的默认 NIC。 :-)

关于windows - 在多宿主 Windows PC 上接收多播消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2988788/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com