2010-06-07 7 views
2

멀티 캐스트/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; }

감사합니다 네 당신의 도움이!

답변

2

문제는 단순한 오타했다. 구조체 구조체 ip_mreq_source 대신 구조체 struct ip_mreq을 사용해야합니다. IP_MULTICAST_IF 옵션을 사용하는 경우. (다른 구조는 IP_ADD_SOURCE_MEMBERSHIP 옵션에 필요합니다.)

잘못된 구조를 사용하면 setsockeopt 함수가 NIC IP 주소가 예상되는 곳에서 0을 찾았을 가능성이 가장 큽니다. Zero는 시스템의 기본 NIC를 선택하는 INADDR_ANY 상수의 값이기도합니다. :-)

1

라우팅 테이블을 확인하거나 변경할 수 있습니다. 그것의 적절한 통계와 거기에 멀티 캐스트 (224.0.0.0, 서브넷 240.0.0.0) 트래픽에 대한 경로가있을 것입니다 :

C:\Users\Cetra>netstat -rn 

***** 

IPv4 Route Table 
=========================================================================== 
Active Routes: 
Network Destination  Netmask   Gateway  Interface Metric 
      0.0.0.0   0.0.0.0 192.168.80.254 192.168.80.99  20 
     127.0.0.0  255.0.0.0   On-link   127.0.0.1 306 
     127.0.0.1 255.255.255.255   On-link   127.0.0.1 306 
    127.255.255.255 255.255.255.255   On-link   127.0.0.1 306 
    192.168.80.0 255.255.255.0   On-link  192.168.80.99 276 
    192.168.80.99 255.255.255.255   On-link  192.168.80.99 276 
    192.168.80.255 255.255.255.255   On-link  192.168.80.99 276 

     224.0.0.0  240.0.0.0   On-link   127.0.0.1 306 
     224.0.0.0  240.0.0.0   On-link  192.168.80.99 276 

    255.255.255.255 255.255.255.255   On-link   127.0.0.1 306 
    255.255.255.255 255.255.255.255   On-link  192.168.80.99 276 

****** 
+0

답장을 보내 주셔서 감사합니다. 라우팅 테이블에 멀티 캐스트 항목을 추가/변경하는 것은 작동하는 작업장입니다. 하지만 아마도 대부분 고객 PC의 라우팅 테이블을 변경할 수 없기 때문입니다. – Basti

+0

해결 방법으로 생각하지 않습니다. 네트워크가 작동하는 방식 일뿐입니다. 고객의 PC가 멀티 홈이 될 수도 있습니까? – Cetra

+0

응용 프로그램은 제품이므로 제외 할 수 없습니다. Windows API 함수로 라우팅 테이블을 변경하는 방법에 대해 이미 생각했습니다 ...하지만 고객 PC에 어떤 부작용이 생길 수 있는지 확신 할 수 없습니다. 그래서 나는 생각을 떨어 뜨렸다. – Basti