C#

멀티캐스트 송수신

Broadcast와 Multicast

하나의 컴퓨터에서 또 다른 하나의 컴퓨터에 데이타를 보내는 것을 Unicast라 하고, 하나의 컴퓨터에서 네트워크 상의 모든 컴퓨터에 데이타를 보내는 것을 Broadcast라 한다. 또한, 한 컴퓨터에서 네트워크 상의 다수의 컴퓨터들에게 데이타를 보내는 것을 Multicast라 한다.

Broadcast와 Multicast를 사용하기 위해서는 UDP 프로토콜을 사용해야 한다. (TCP는 이러한 기능을 제공하지 않는다) UDP에서 Broadcast를 사용하기 위해서는 전송 타겟 IP를 "255.255.255.255"로 설정하면 된다. Broadcast는 서브네트워크 내의 모든 컴퓨터에 데이타를 전달하는 기능으로 일반적으로 한 라우터 내에서만 사용된다.

UDP에서 Multicast를 사용하기 위해서는 224.0.0.0 부터 239.255.255.255 사이의 IP를 사용하면 되는데, Multicast IP 중 224.0.0.0 부터 224.0.0.255까지가 라우팅 프로토콜과 네트워크 트래픽 제어용으로 사용되어 이미 예약되어 있기 때문에 실제로는 224.0.1.0 부터 239.255.255.255 까지 중 IP 하나를 선택해서 사용한다.

UDP 멀티캐스팅

UDP를 사용하여 멀티캐스트로 데이타를 전송하기 위해서는 224.0.1.0 부터 239.255.255.255 까지 중 IP 하나를 선택해서 멀티캐스팅 IP로 사용하고, 사용하지 않는 임의의 포트를 정한다. 예를 들어, 멀티캐스트 IP를 229.1.1.229 으로 정하고, 포트를 5500 으로 지정하였다고 가정하자. UDP에서 229.1.1.229:5500 으로 데이타그램을 전송하면, 이는 네트워크 내 "멀티캐스트 그룹"에 전송되는데, 네트워크 내 각 컴퓨터는 이 "멀티캐스트 그룹"에 명시적으로 가입함으로써 그룹이 형성된다.

예를 들어 사내 네트워크 내에 100 대의 컴퓨터가 있고 이 중 한 사람이 동영상 강의를 한다고 했을때, 사원 중 20명이 강의를 듣는다고 하면 이들 20명이 멀티캐스트 IP 229.1.1.229 으로 가입(Join)하여 멀티캐스트 그룹을 형성한다. 물론 수신 프로그램에서 이 멀티캐스트 IP와 포트를 알고 있어야 하고 또한 해당 포트를 수신할 수 있도록 Firewall에서 열어 두어야 한다.

멀티캐스트 송신

멀티캐스트로 데이타를 보내기 위해서는 UdpClient 혹은 Socket 클래스를 사용할 수 있다. 아래 예제는 UdpClient를 사용하여 멀티캐스트로 데이타를 보내는 방법을 예시한 것이다.

// 멀티캐스트 전송(Send)

static void Main(string[] args)
{            
    // (1) UdpClient 객체 성성
    UdpClient udp = new UdpClient();

    // (2) Multicast 종단점 설정            
    IPEndPoint multicastEP = new IPEndPoint(IPAddress.Parse("229.1.1.229"), 5500);
    
    for (int i = 1; i <= 60; i++)
    {                  
        byte[] dgram = Encoding.ASCII.GetBytes("Msg#" + i);

        // (3) Multicast 그룹에 데이타그램 전송      
        udp.Send(dgram, dgram.Length, multicastEP);

        Console.WriteLine("Msg#" + i);
        Thread.Sleep(1000);
    }
}

기본적인 스텝은 먼저 (1) UdpClient 객체를 생성하고, (2) 멀티캐스트 종단점을 정한 후, (3) UdpClient 객체의 Send() 메서드를 사용하여 멀티캐스트 종단점으로 데이타그램을 보내면 된다.

선택사항이지만 멀티캐스트 TTL을 지정할 수도 있다. TTL이란 Time-to-live의 약자로서 한 패킷이 라우터를 한번 통과할 때마다 하나씩 줄어드는 값으로 0이 되면 다음 라우터로 패킷이 전달되지 않는다. 즉, TTL이 32란 의미는 개념적으로 32개 라우터를 통과할 수 있다는 뜻이다. 멀티캐스트 TTL은 어느 네트워크 범위만큼 멀티캐스팅을 할 지를 결정하게 되는 것으로, 프로그램의 성격에 따라 필요할 수 있다. 멀티캐스트 TTL은 멀티캐스팅을 하는 Sender에만 필요하며, 수신 프로그램에서는 사용할 필요가 없다.
참고로 위의 예제에서 UdpClient 객체인 udp의 Client 속성은 그 타입이 Socket 객체이며 UDP가 사용하는 내부 소켓에 접근하기 위해 사용된다. Socket 객체의 SetSocketOption() 메서드는 소켓 객체의 다양한 고급 옵선을 지정하기 위해 사용된다.

멀티캐스트 수신

멀티캐스트된 데이타를 수신 위해서 역시 UdpClient 혹은 Socket 클래스를 사용할 수 있다. 아래 예제는 UdpClient를 사용하여 멀티캐스트로부터 데이타를 수신하는 방법을 예시한 것이다.

// 멀티캐스트 수신(Receive)

static void Main(string[] args)
{
    // (1) UdpClient 객체 성성
    UdpClient udp = new UdpClient();

    // (2) UDP 로컬 IP/포트에 바인딩            
    // udp.Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.ReuseAddress, true);
    IPEndPoint localEP = new IPEndPoint(IPAddress.Any, 5500);
    udp.Client.Bind(localEP);            
    
    // (3) Multicast 그룹에 Join
    IPAddress multicastIP = IPAddress.Parse("229.1.1.229");
    udp.JoinMulticastGroup(multicastIP);          
    
    IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);

    while (!Console.KeyAvailable)
    {
        // (4) Multicast 수신
        byte[] buff = udp.Receive(ref remoteEP);

        string data = Encoding.ASCII.GetString(buff, 0, buff.Length);
        Console.WriteLine(data);
    }
}
기본적인 스텝은 먼저 (1) UdpClient 객체를 생성하고, (2) 수신 컴퓨터의 로컬 IP와 멀티캐스트 포트를 사용하여 로컬 포트에 바인드한다. 위의 멀티캐스트 송신 예제에서 5500 포트를 사용하였으므로, 여기서 5500 포트에 바인드한다. 이는 UdpClient 객체의 Client 속성으로부터 Socket 객체를 얻은 후 Bind() 메서드를 사용하면 된다. (3) 다음으로 멀티캐스트 IP 주소를 사용하여 멀티캐스트 그룹에 가입하면 멀티캐스트 패킷을 받아 들일 수 있게 된다. (4) 그룹 가입 후 Receive() 메서드를 사용하여 데이타를 읽어 들여 처리하면 된다.

멀티캐스트 환경 설정

위와 같이 멀티캐스트 송수신 프로그램이 완료되면, 이를 서로 다른 컴퓨터에서 혹은 동일 컴퓨터에서 실행할 수 있다. 그런데 컴퓨터/네트워크 환경 설정에 따라 멀티캐스트가 정상적으로 동작하지 않을 수 있는데, 아래는 이때 필요한 몇가지 점검사항들이다.

  • 라우터의 IGMP 설정 : Broadcast와 Multicast는 IGMP (Internet Group Management Protocol)을 사용하는데, 최근의 라우터들은 IGMP를 Disable하는 경우가 많다. 이 경우 멀티캐스트 송신하더라도 수신할 수 없게 되므로 이를 Enable해 주어야 한다. (라우터마다 설정 메뉴가 다르므로 해당 라우터의 매뉴얼을 참고)
  • Firewall 포트 허용 : Multicast 송신을 할 때, 멀티캐스트 IP주소의 특정 포트(위의 예제는 5500)로 데이타그램을 보내는데, 이 포트번호가 수신 컴퓨터의 Firewall 에서 허용되어 있어야 한다. 일반적으로 윈도우즈에서 수신 프로그램을 실행하면 Firewall 허용 설정 다이얼로그가 나오는데, 이때 Private/Domain/Public 네트워크 허용 범위를 지정해 준다. 만약 이 범위를 잘못 설정하면 수신할 수 없다.
  • 네트워크 인터페이스 : 하나의 컴퓨터에는 여러 개의 네트워크 카드(가상 네트워크 포함)를 가질 수 있다. 수신 프로그램에서 로컬 IP를 바인드할 때 잘못된 네트워크 인터페이스를 선택하는 (혹은 선택되는) 경우가 있는데, 이 경우 수신이 이루어 지지 않는다. 특히, VirtualBox 등과 같은 가상 네트워크 인터페이스가 있으면, 이런 오류가 자주 발생한다. 해결책은 물리적인 LAN 혹은 Wireless Card의 네트워크 인터페이스를 알아내어 사용하거나 가상 네트워크 인터페이스를 미리 Disable 한다.
만약 계속 문제가 발생하면, WireShark 같은 네트워크 모니터링 도구를 송신측과 수신측에서 사용하여 송신이 제대로 되는지, 수신이 제대로 되는지를 체크해 본다. 아래는 WireShark을 사용하여 UDP 패킷을 잡아 본 예이다.

(참고) 하나의 socket으로 여러 개의 멀티캐스트 그룹에 Join할 수 있다(소켓 옵션 사용). 또한, 여러 개의 컴퓨터는 하나의 멀티캐스트 그룹에 데이타를 보낼 수 있다.

Socket을 사용한 멀티캐스팅 예제

Socket 클래스를 사용한 멀티캐스트는 UdpClient 클래스를 사용하는 방법과 개념적으로 비슷하지만, 멀티캐스트 그룹에 Join하는 부분에 약간의 문법적인 차이가 있다. 아래는 Socket을 사용하여 멀티캐스트로 송신하는 예제이다.

// 소켓 생성 및 필요시 소켓 옵션 지정
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 32);

// 멀티캐스트 종단점
IPAddress multicastIP = IPAddress.Parse("239.100.100.100");
IPEndPoint ep = new IPEndPoint(multicastIP, 5500);

// 데이타 송신
byte[] buff = Encoding.ASCII.GetBytes("Hello");
sock.SendTo(buff, 0, buff.Length, SocketFlags.None, ep);

sock.Close();

아래는 Socket을 사용하여 멀티캐스트로 수신하는 예제이다.

// 소켓 생성 및 필요시 소켓 옵션 지정
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
// sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.ReuseAddress, true);

// 소켓 바인드
sock.Bind(new IPEndPoint(IPAddress.Any, 5500));

// 멀티캐스트 그룹에 가입
IPAddress multicastIP = IPAddress.Parse("239.100.100.100");
sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(multicastIP, IPAddress.Any));

byte[] buff = new byte[1024];
EndPoint ep = new IPEndPoint(IPAddress.Any, 0);            

// 데이타 수신
int n = sock.ReceiveFrom(buff, 0, buff.Length, SocketFlags.None, ref ep);

Console.WriteLine(Encoding.ASCII.GetString(buff, 0, buff.Length));

// 멀티캐스트 그룹에서 탈퇴
sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.DropMembership, new MulticastOption(multicastIP, IPAddress.Any));

sock.Close();

본 웹사이트는 광고를 포함하고 있습니다. 광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.

Previous Next Print