TCP와 구별괴는 UDP의 특징으로 브로드캐스팅과 멀티캐스팅을 들 수 있다. 이를 이용하면 다자 간 통신을 쉽게 구현할 수 있다. 통신에 참여하는 개체 간 상호 작용을 송신자와 수신자의 개수에 따라 분류하면 다음과 같다.
(7-16 그림)
여기에서는 UDP를 이용한 브로드캐스팅 기법을 다룰 것이다.
브로드캐스팅은 송신자가 보낸 데이터 하나를 다수의 수신자가 받는 방식이다. 데이터 복사본을 여러 개 만들어 보내는 것이 아니기 때문에 송신자 관점에서 보면 상당히 효율적인 기술이라고 볼 수 있다.
(7-17 그림)
위 그림은 이더넷(Ethernet)에서 브로드캐스팅 메세지를 보내는 상황을 나타낸 것이다. 송신자가 보내는 (하나의) 메세지는 이더넷을 통한 모든 개체에 전달되고, 각 개체는 이 메세지가 브로드캐스트 주소로 보낸 것임을 확인하고 읽어들인다.
소켓 응용 프로그램에서 브로드캐스트 데이터를 보내려면 다음 절차를 따라야 한다. 브로드캐스트 데이터를 받는 쪽에서는 프로토콜과 포트 번호만 일치 시키면 된다.
```
BOOL bEnable = TRUE;
retval = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *) &bEnable, sizeof(bEnable));
if (retval == SOCKET_ERROR)
err_quit("setsockopt()");
```
socket()
함수로 생성한 소켓 디스크립터는 기본적으로 유니캐스팅만 가능하다. 소켓 옵션 중 SO_BROADCAST
를 사용하면 브로드캐스팅을 활성화할 수 있다.```
// 소켓 주소 구조체를 초기화한다.
SOCKADDR_IN remoteaddr;
ZeroMemory(&remoteaddr, sizeof(remoteaddr));
remoteaddr.sin_family = AF_INET;
remoteaddr.sin_addr.s_addr = inet_addr("255.255.255.255");
remoteaddr.sin_port = htons(9000);
// 송신용 버퍼를 선언하고 데이터를 넣는다.
char buf[BUFSIZE];
...
// sendto() 함수로 데이터를 보낸다.
retval = sendto(sock, buf, strlen(buf), 0, (SOCKADDR *) &remoteaddr, sizeof(remoteaddr));
if (retval == SOCKET_ERROR) 오류 처리;
printf("%d 바이트를 보냈습니다.\n", retval);
```
브로드캐스트 데이터를 보내는 코드는 IP 주소 부분을 제외하면 유니캐스트 데이터를 보내는 것과 동일하다. 따라서 브로드캐스트를 위한 IP 주소의 종류만 알면 된다. IPv6에서는 브로드캐스팅을 지원하지 않기 때문에 IPv4 주소만 설명할 것이다.IPv4 주소는 크게 네트워크 ID와 호스트 ID로 나눌 수 있다. 서브넷(subnet)을 사용하는 경우, 호스트 ID의 일부는 서브넷 ID로 사용된다. 브로드캐스팅용으로 예약되어 있는 IPv4 주소는 아래 그림과 같다.
(7-18 그림)
ws2def.h
파일에 INADDR_BROADCAST
(0xfffffffff; 255.255.255.255) 값으로 정의되어 있다.UDP 소켓을 이용해 브로드캐스트 데이터를 보내는 프로그램과 받는 프로그램을 적성해 보았다. 실습의 편의를 위해 지역 브로드캐스트 주소(255.255.255.255)를 사용하였으며, 두 응용 프로그램의 동작은 아래와 같다.
(7-22 그림)
작성된 코드는 아래에 존재한다.
https://github.com/LEEBONGHAK/TCP-IP_window_socket/tree/main/Chapter07/Broadcast
참고 자료
김성우 저, "TCP/IP 윈도우 소켓 프로그래밍", 한빛아카데미, 2018