Easy ways

[Linux/C 언어] 멀티캐스트 송신 코드 및 테스트 (Multicast Sender) 본문

프로그래밍 언어/C언어

[Linux/C 언어] 멀티캐스트 송신 코드 및 테스트 (Multicast Sender)

softColors 2021. 2. 26. 16:46
반응형

오늘은 멀티캐스트 송신부를 구현하고 테스트해보겠습니다.

멀티캐스트는 송신부 수신부가 따로 구현되는 경우가 많기 때문에

별도의 툴을 사용해서 생성한 코드를 테스트해보겠습니다.

 

구현 환경 : 리눅스

 

멀티캐스트 송신부는 그냥 그룹에 신호를 보내기만 하면 되기 때문에 

그냥 UDP 통신과 비슷하지만,

따로 설정해주어야 하는 파라미터들이 있기 때문에 그것들에 대해서 한번 다뤄보겠습니다.

 

멀티캐스트에 대한 개념적 설명은 아래 링크에서 다루고 있으니 참고 바랍니다.

softtone-someday.tistory.com/14

 

멀티캐스트(multicast)란? [feat. 브로드캐스트(broadcast)]

오늘은 통신 방식 중 하나인 멀티캐스트 대하여 알아보겠습니다. 멀티 캐스트(multicast) 멀티캐스트란 무엇일까요? 멀티캐스트는 같은 데이터를 특정 그룹에게 보내주어야 할 때 사용하는 인터넷

softtone-someday.tistory.com

 

 

이더넷(eth0) 설정


먼저 멀티캐스트는 코드 비중보다는 OS가 할 수 있느냐 없느냐에 더 많은 것이 달려있습니다.

 

먼저 ifconfig 명령으로 현재 이더넷 상태를 확인합니다.

(예시를 들기 위해 eth0번 사용)

 

 

우선적으로, 내 컴퓨터의 IP를 어디다 적어두세요! 필요합니다

 

여기서 빨간 줄로 밑줄 친 곳에 Multicast라고 적혀있는 것이 없다면

아래 명령으로 멀티캐스트를 활성화해줍니다.

 

## enable multicast
# ifconfig eth0 multicast  

 

활성화가 안된다면 사용하고 있는 보드나 컴퓨터가 멀티캐스트를 지원하고 있는지 알아보셔야 합니다.

 

혹시 나중에라도 멀티캐스트를 끄고 싶을 때는 아래 명령어를 사용하세요

## disable multicast 
# ifconfig eth0 -multicast  

 

 

 

 

코드 구현


멀티 캐스트 송신 예제 코드는 다음과 같습니다.

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main (void)

{
  
    int sockfd, send_len;
   	struct sockaddr_in multicast_addr;	
    struct in_addr     local_addr;

    // Max Router Num
    char ttl=5;
  
    // multicast addr
    char *multicast_ip = "225.192.0.10";
    int   multicast_port  = 50000;

    // send device ip address [current computer]
    char *local_ip      = "192.168.0.10";

    // sending message
    char *send_message ="Hello multicast";

    // generatae socket
    sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sockfd < 0) 
    {
        printf("Socket open error\n");
        return -1;
    }

    // setting multicast address
    multicast_addr.sin_family      = AF_INET;
    multicast_addr.sin_addr.s_addr = inet_addr(multicast_ip);
    multicast_addr.sin_port        = htons(multicast_port);

    // set the maximum number of routers.
    if(setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL,(void *)&ttl,sizeof(ttl))<0)
    {
        printf("Socket setsockopt error.[ttl]\n");

        close(sockfd);
        return -1;
    }

    // set the Ip address to be transmitted(local ip)
    local_addr.s_addr = inet_addr(local_ip);    
    if(setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF,(char *)&local_addr, sizeof(local_addr))<0)
    {
        printf("Socket setsockopt error.[Interface]\n");
        close(sockfd);
        return -1;
    }

    // send message
    send_len = sendto(sockfd, send_message, strlen(send_message), 0, (struct sockaddr*)&multicast_addr, sizeof(multicast_addr));
    printf("send len : %d\n",send_len);
    if( send_len < 0 )
    {
        printf("Sending multicast message error");
    }
    else
        printf("Sending multicast message...Success\n");


    close(sockfd);
    return 0;
}

 

 

변수 선언

 

먼저 선언된 변수를 보겠습니다. 

    int sockfd, send_len;
   	struct sockaddr_in multicast_addr;	
    struct in_addr     local_addr;

    // Max Router Num
    char ttl=5;
  
    // multicast addr
    char *multicast_ip = "225.192.0.10";
    int   multicast_port  = 50000;

    // send device ip address [current computer]
    char *local_ip      = "192.168.0.10";

    // sending message
    char *send_message ="Hello multicast";

 

두 번째 줄과 세 번째 줄을 보시면 

multicast_addr과 local_addr이라는 항목을 볼 수 있습니다.

 

multicast_addr 은 우리가 신호를 보낼 목적지인 멀티캐스트 주소를 쓸 변수이고

local_addr은 위에서 확인한 내 컴퓨터의 ip 주소를 적어줄 겁니다.

 

멀티캐스트 전송을 할 때에는

내 컴퓨터에서 어느 포트(지금의 경우 eth0)로 멀티캐스트 문장을 보낼지 설정해주어야 하기 때문에 

2개의 ip 주소가 필요로 합니다. 

 

이는 변수 선언의 multicast_ip, local_ip에 선언되어있습니다.

  •     multicast_ip  : 멀티캐스트로 보낼 ip 주소
  •     local_ip       : 내 컴퓨터의 ip 주소

ttl이라는 변수는 멀티캐스트 신호가 지나갈 수 있는 최대 라우터 개수입니다.

send_messge는 멀티캐스트로 보낼 문장입니다.

 

 

소켓 설정

 

소켓을 설정하는 부분에서 조금 생소한 설정을 볼 수 있습니다. 

 // set the maximum number of routers.
    if(setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL,(void *)&ttl,sizeof(ttl))<0)
    {
        printf("Socket setsockopt error.[ttl]\n");

        close(sockfd);
        return -1;
    }

IP_MULTICAST_TTL 은 멀티캐스트로 지날 수 있는 최대 라우터 개수를 설정을 의미합니다.

 

위에서 int ttl = 5;라고 선언했기 때문에 

예제 코드에서 전송된 신호가 지날 수 있는 라우터의 개수는 5개입니다. 

 

    // set the Ip address to be transmitted(local ip)
    local_addr.s_addr = inet_addr(local_ip);    
    if(setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF,(char *)&local_addr, sizeof(local_addr))<0)
    {
        printf("Socket setsockopt error.[Interface]\n");
        close(sockfd);
        return -1;
    }

IP_MULTICAST_IF 이 옵션이 가장 중요한데요 멀티캐스트로 전송할 인터페이스 주소를 지정해주는 옵션입니다.

간단하게 설명하자면 보낼 신호의 출발지라고 할 수 있습니다. 

인터페이스 주소는 ifconfig로 볼 수 있는 설정되어있는 ip 주소만을 사용할 수 있습니다.

 

그림으로 그리자면 아래와 같습니다. 

 

sendto를 사용하여 메시지를 보내면 설정된 인터페이스 ip를 거쳐서 목적지로 가는 겁니다.

 

테스트(wireshark)


자 이제 테스트만 남았습니다.

 

멀티캐스트를 수신하는 프로그램을 만드는 것이 좀 더 정확할 수 있지만,

간단하게 여러 개의 ip로의 전송을 테스트하려면 패킷을 잡아주는 툴을 쓰는 것이 더 효율적일 수 있습니다.

 

저는 확인용 툴로 와이어 샤크(wireshark)라는 프로그램을 사용했습니다.

 

www.wireshark.org/#download

 

Wireshark · Go Deep.

What is SharkFest? SharkFest™, launched in 2008, is a series of annual educational conferences staged in various parts of the globe and focused on sharing knowledge, experience and best practices among the Wireshark® developer and user communities. Shar

www.wireshark.org

 

 

와이어 샤크에 들어가서 내 컴퓨터 IP 혹은 멀티캐스트 주소로 필터를 생성하고

[필터 설정 : ip.addr == 내 컴퓨터 IP  또는  ip.addr == 멀티캐스트 주소]

 

위 코드를 실행하면 아래와 같이 제가 설정한 멀티캐스트 주소로 데이터가 전송되었음을 확인할 수 있습니다.

간단하죠?

 

 

 

전송된 문장을 확인하기 위해 저 패킷을 더블 클릭하면

 

아래 사진과 같이 문장이 잘 전송되었음을 확인할 수 있습니다.

 

 

 

 

반응형
Comments