본문 바로가기

C#

C# 멀티캐스트 안됨 해결법 / 랜카드 NIC / C++도 참고가능

네트워크 프로그램이 필요해서 C#으로 Sender와 Receiver를 만들어 실행했는데, 처음에는 이상이 없었습니다. 이상이 있으면 MSDN 샘플이 잘못된 것일테니까요. 그런데 각기 다른 컴퓨터를 두고 실행해보면 수신을 받지 못하는 현상이 발생했습니다. 하루이틀 삽질을 통해 원인을 알아내었습니다.

 

먼저, 멀티캐스트는 먼저 살펴봐야할 3가지 환경구성이 있습니다.

 

1. 라우터 IGMP

라우터(또는 공유기) 설정 페이지를 열어 잘 찾아보면 IGMP 항목이 있으며 활성화가 되어있어야 멀티캐스트 통신이 가능해집니다.

 

2. 방화벽

인/아웃바운드 설정에서 통신할 포트를 열어줘야 합니다. 또는 방화벽을 다 끄고 테스트

 

3. 네트워크 인터페이스 - 문제가 생긴 부분

Sender에서 패킷이 나갈 네트워크 인터페이스(랜 어댑터)의 설정이 필요합니다.

 

NetworkInterface.GetAllNetworkInterfaces() 메소드를 호출하여 값을 살펴보면 현재 컴퓨터에서 사용가능한 어댑터들을 확인할 수 있는데, 패킷이 외부의 인터넷(또는 내보낼 네트워크)에 연결된 어댑터가 아닌 전혀 관련없는 어댑터에서 송신하고 있을 가능성이 있습니다.

 

이를 해결할 방법들

1. 사용하지 않는 어댑터 미리 비활성화

2. 사용자에게 랜카드를 선택하게 하기

3. 프로그래머가 수동으로 처리하기

 

저는 3번을 택했으며, 향후 상황에 따라 2번으로 변경할 예정입니다.

 


원인

제 경우에는 외부 컴퓨터와 연결된 어댑터가 아닌 내부 가상 로컬 네트워크에 패킷을 전달하는 상황이었습니다. 내부에 전달하고 있었으니, 한 컴퓨터에서 Sender와 Receiver는 문제가 없이 작동했던 것이였습니다. 원했던 것은 외부 컴퓨터와의 통신이였으니 어댑터를 지정해주어야 합니다.

 

코드 일부

1
2
3
4
5
6
7
8
9
10
11
12
13
        IPv4InterfaceProperties properties = null;
        NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
        foreach (NetworkInterface n in nics)
        {
            if (n.OperationalStatus == OperationalStatus.Up &&
                n.NetworkInterfaceType != NetworkInterfaceType.Loopback &&
                (int)n.NetworkInterfaceType != 53// https://github.com/tpn/winsdk-10/blob/master/Include/10.0.14393.0/shared/ipifcons.h 마샬링되어진 매크로. 53번은 가상 네트워크를 말함
            {
                properties = n.GetIPProperties().GetIPv4Properties();
            }
        }
 
        senderSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, (int)IPAddress.HostToNetworkOrder(properties.Index));
cs

말그대로 통신하고 싶은 어댑터를 선택하기 위해, 현재 컴퓨터상에서 조회되는 어댑터 목록을 보면서 적절히 필터링을 하고 Socket의 SetSocketOption 메소드의 파라미터에서 MulticastInterface 열거형을 지정, 필터링된 어댑터의 값을 넣어주었습니다.

 

NetworkInterfaceType 열거형에는 가상 네트워크 항목이 정의되어 있지 않은데, 

 

가상 네트워크는 없는 것 같다

 

53은 도대체 뭘까

 

어댑터 항목을 조회하여 가상 로컬 어댑터의 Type을 확인해보면 53이란 값을 리턴하고 있음을 알 수 있습니다. 이는 C#에 정의된 것이 아닌 C++ 매크로에 정의되어 C# 마샬링을 통해 출력되고 있습니다.

 

https://github.com/tpn/winsdk-10/blob/master/Include/10.0.14393.0/shared/ipifcons.h

 

GitHub - tpn/winsdk-10

Contribute to tpn/winsdk-10 development by creating an account on GitHub.

github.com

에서 네트워크 인터페이스 매크로들을 살펴볼 수 있는데 C# 열거형에서 미처 정의되지 못한 값들은 C++에 정의되어 있습니다.

 

#define IF_TYPE_PROP_VIRTUAL 53으로 가상 네트워크임을 알 수 있습니다.

 

최종적으로, 해당 항목도 필터링하여 원하는 어댑터만 남겼고, 해당 어댑터의 IPv4 프로퍼티의 값을 SetSocketOption을 호출하여 지정해준 것입니다. 그리고 외부 컴퓨터와 멀티캐스트 통신에 성공했습니다.

 


C++

네트워크 관련한 항목에서 C#과 C++은 상당부분(사실상 C++ 래핑된것 같은 느낌) 동일하기 때문에 이 해결법을 참고하면 C++ Socket에서도 해결할 수 있을 것입니다.

 

setsockopt() 함수에서 위 C#코드와 마찬가지로 인터페이스에 대해 매크로가 정의되어 있습니다.

setsockopt(socket, IPPROTO_IP, IP_MULTICAST_IF, 필터링된 어댑터....)

이런식으로 하면 될 것 같습니다.

 

내용이 도움이 되었길 바랍니다.

 


 

 

C# 멀티캐스트 안됨 해결법 두번째

https://healp.tistory.com/95 C# 멀티캐스트 안됨 해결법 / 랜카드 NIC / C++도 참고가능 네트워크 프로그램이 필요해서 C#으로 Sender와 Receiver를 만들어 실행했는데, 처음에는 이상이 없었습니다. 이상이 있

healp.tistory.com

위 방법으로 해결이 불가능했거나 사용도중 문제가 생겼다면 두번째 방안에 대해 작성해두었으니 참고바랍니다.