iBetter Books
수정

브로드캐스트와 멀티캐스트

지금까지의 통신은 모두 일대일이었습니다. 한 사람이 다른 한 사람에게 보냈습니다. 그런데 한 번에 여러 사람에게 같은 데이터를 보내야 할 때가 있습니다. 강당에서 한 사람이 마이크로 모두에게 말하는 것처럼 말입니다. UDP는 이 일을 잘합니다. TCP는 연결이 일대일이라 이렇게 할 수 없지만, 연결이 없는 UDP는 한 번 던진 데이터그램을 여럿이 받게 할 수 있습니다. 그 두 가지 방법, 브로드캐스트와 멀티캐스트를 살펴봅니다.

브로드캐스트, 모두에게 외치기

브로드캐스트는 같은 네트워크에 있는 모든 컴퓨터에게 한 번에 데이터를 보내는 방법입니다. 마을 광장에서 확성기로 외치면 광장 안 모두가 듣는 것과 같습니다. 누가 듣는지 신경 쓰지 않고, 그저 모두에게 뿌립니다.

브로드캐스트를 쓰려면 소켓에 특별한 허락을 받아야 합니다. 기본적으로 막혀 있기 때문입니다. setsockoptSO_BROADCAST 옵션을 켜면 됩니다.

# 새 파일: broadcast_send.pyimport socketsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)sock.sendto("모두에게 알립니다".encode(), ("255.255.255.255", 9800))print("브로드캐스트를 보냈습니다")sock.close()

255.255.255.255라는 특별한 주소가 브로드캐스트 주소입니다. 이 주소로 보내면 같은 네트워크의 모든 컴퓨터가 받을 수 있습니다.

다만 브로드캐스트에는 한계가 있습니다. 같은 네트워크 안에서만 닿고 라우터를 넘지 못합니다. 그리고 듣고 싶지 않은 컴퓨터에게도 무차별로 전해져 네트워크에 부담을 줍니다. 그래서 요즘은 더 똑똑한 방법인 멀티캐스트가 선호됩니다.

멀티캐스트, 듣고 싶은 사람에게만

멀티캐스트는 관심 있는 사람에게만 보내는 방법입니다. 라디오 방송에 빗댈 수 있습니다. 특정 주파수로 방송을 내보내면, 그 주파수에 채널을 맞춘 사람만 듣습니다. 채널을 맞추지 않은 사람에게는 들리지 않습니다.

여기서 주파수에 해당하는 것이 멀티캐스트 그룹 주소입니다. 224.0.0.0부터 239.255.255.255까지가 멀티캐스트 전용으로 예약된 주소 대역입니다. 보내는 쪽은 이 그룹 주소로 데이터를 보내고, 받고 싶은 쪽은 그 그룹에 가입합니다. 가입한 사람만 데이터를 받습니다.

멀티캐스트 받기

받는 쪽은 그룹에 가입하는 절차가 필요합니다.

# 새 파일: mcast_recv.pyimport socketimport structGROUP = "224.1.1.1"PORT = 9800sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)sock.bind(("", PORT))mreq = struct.pack("4sl", socket.inet_aton(GROUP), socket.INADDR_ANY)sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)print("멀티캐스트 그룹 가입, 수신 대기")for _ in range(2):    data, addr = sock.recvfrom(1024)    print(f"{addr} 로부터: {data.decode()}")sock.close()

핵심은 그룹 가입 부분입니다. IP_ADD_MEMBERSHIP 옵션으로 운영체제에게 "이 그룹의 데이터를 받고 싶다"고 알립니다. 함께 넘기는 mreq는 어느 그룹에 가입할지를 담은 정보로, 그룹 주소와 어느 네트워크 카드로 받을지를 묶어 만듭니다. INADDR_ANY는 운영체제에게 적절한 카드를 알아서 고르게 맡긴다는 뜻입니다. 가입한 뒤에는 평범한 recvfrom으로 데이터를 받습니다. 라디오 채널을 맞춘 셈입니다.

bind에서 주소를 빈 문자열로 둔 것도 눈여겨볼 점입니다. 특정 주소가 아니라 그 포트로 오는 멀티캐스트를 모두 받겠다는 의미입니다.

멀티캐스트 보내기

보내는 쪽은 훨씬 간단합니다. 그룹 주소로 그냥 보내면 됩니다.

# 새 파일: mcast_send.pyimport socketGROUP = "224.1.1.1"PORT = 9800sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)for message in ["공지 하나", "공지 둘"]:    sock.sendto(message.encode(), (GROUP, PORT))    print(f"보냄: {message}")sock.close()

보내는 쪽은 그룹에 가입할 필요가 없습니다. 그저 그룹 주소 224.1.1.1sendto를 하면 됩니다. 가입한 모든 수신자가 이 데이터를 받습니다. IP_MULTICAST_TTL 옵션은 이 데이터그램이 몇 개의 라우터를 넘어갈 수 있는지를 정합니다. 값이 2면 두 단계까지 퍼진다는 뜻으로, 너무 멀리 퍼지지 않도록 제한하는 안전장치입니다.

실행해 보기

수신자를 먼저 띄워 그룹에 가입시킨 뒤, 송신자를 실행합니다.

# 파일: 터미널 1 (수신)python3 mcast_recv.py
# 파일: 터미널 2 (송신)python3 mcast_send.py

송신 쪽에는 보낸 기록이, 수신 쪽에는 받은 기록이 남습니다.

멀티캐스트 그룹 가입, 수신 대기
('192.168.75.243', 52810) 로부터: 공지 하나
('192.168.75.243', 52810) 로부터: 공지 둘

한 번 보낸 데이터를 그룹에 가입한 수신자가 받았습니다. 수신자를 여러 개 띄우면 모두가 같은 데이터를 받습니다. 이것이 일대다 통신의 힘입니다.

멀티캐스트는 같은 데이터를 여러 곳에 실시간으로 뿌려야 하는 곳에서 빛납니다. 사내 방송, 주식 시세 배포, 여러 화면에 동시에 영상을 뿌리는 시스템 같은 곳입니다. 한 번만 보내면 네트워크가 알아서 가입자들에게 복제해 전하므로, 수신자가 늘어도 송신자의 부담은 그대로입니다.

여러 상대에게 뿌리는 법까지 배웠습니다. 이제 이 PART에서 배운 UDP를 한데 모아, 여러 센서가 실시간으로 데이터를 쏘아 보내는 수집기를 만들어 봅니다.

04장. 브로드캐스트와 멀티캐스트 — 소설처럼 읽는 소켓 프로그래밍 | iBetter Books