멀티 캐스트/udp 기반의 여러 네트워크 인터페이스가있는 PC에서 진단 도구를 개발 중입니다. 사용자는 NIC를 선택할 수 있고, 응용 프로그램은 소켓을 만들고,이 NIC에 바인드하여 특정 멀티 캐스트 그룹에 추가합니다.멀티 홈 Windows PC에서 멀티 캐스트 메시지 받기
멀티 캐스트 메시지를 보내는 것이 정상적으로 작동합니다. 그러나 메시지 수신은 소켓을 내 PC의 특정 NIC에 바인딩하는 경우에만 성공합니다. Windows에서 항상 GetAdapterInfo 함수가 반환 한 첫 번째 NIC 인 멀티 캐스트 메시지를 수신하기위한 '기본'NIC가있는 것처럼 보입니다.
Wireshark를 사용하여 네트워크를 모니터링하고 NIC에서 "IGMP Join Group"메시지가 전송되지 않았 음을 발견했습니다.이 때 '기본'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"); }
}
반환 0; }
감사합니다 네 당신의 도움이!
답장을 보내 주셔서 감사합니다. 라우팅 테이블에 멀티 캐스트 항목을 추가/변경하는 것은 작동하는 작업장입니다. 하지만 아마도 대부분 고객 PC의 라우팅 테이블을 변경할 수 없기 때문입니다. – Basti
해결 방법으로 생각하지 않습니다. 네트워크가 작동하는 방식 일뿐입니다. 고객의 PC가 멀티 홈이 될 수도 있습니까? – Cetra
응용 프로그램은 제품이므로 제외 할 수 없습니다. Windows API 함수로 라우팅 테이블을 변경하는 방법에 대해 이미 생각했습니다 ...하지만 고객 PC에 어떤 부작용이 생길 수 있는지 확신 할 수 없습니다. 그래서 나는 생각을 떨어 뜨렸다. – Basti