네트워크 상에서 IP 주소를 통해서 기기간 위치를 찾고 통신을 한다고 생각하지만 IP 주소라는 것은 추상적인 개념이고, 우리가 약속하고 부여한 번호에 불과하다.
가령 IP 주소가 존재하지 않는다면 기기간 통신이 불가능할까? 아니다
IP 주소라는건 우리가 네트워크를 형성해서 원거리 통신을 가능하게 만든 기술이다
원거리 통신이라는 개념 이전에 로컬 네트워크(물리적 연결) 에서 통신이 우선이였을 것이고, 그 때 사용되는 것은 IP 가 아닌 2계층에 해당하는
Mac 주소
이다.
Mac Address
란 네트워크 상에서 서로를 구분하기 위해 Device 마다 할당된 물리적 주소를 의미한다
뜬근없이 Mac 주소에 대해 설명하는 이유는 기기간 통신에 기본적으로 사용되는 주소가 이 Mac 주소이기 때문이다.
실제로 원거리 통신을 할 때에도 상대방의 맥 주소를 알아야 가능한데, 목적지 주소만 알면서 그곳에 있는 기기의 맥 주소를 아는 것은 쉽지 않다
따라서 ARP(Address Resolution Protocol)
라는 기술을 사용하는데 우선 본문에서는 설명을 생략한다
아무튼 상대방의 맥 주소가 있어야만 나와 물리적으로 연결된 기기를 통해서 원거리에 있는 기기에 쭉쭉 연결이 가능하다
통신계층 별로 하드웨어가 나뉜다고 생각하면 쉬운데, 이 맥주소를 저장하고 검증하는 하드웨어인 랜카드
는 2계층에 존재한다.
1:1 통신을 수행하는 통신 방식
데이터 전송 시 2계층에서 처리하는 프레임 헤더에 출발지와 목적지 Mac 주소를 미리 써넣는다
따라서 타겟 네트워크에 도착했을 때 해당 네트워크에 있는 기기들에게
이렇게 묻는다 "목적지 맥 주소와 같은 기기이신가요?"
그럼 해당 질문에 대한 검증을 누가할까? 바로 위에서 언급한 랜카드이다.
랜카드가 검증하고, 통과(내가 찾는 목적지) 한다면 통신을 시작하고, 그렇지 않다면 랜카드 선에서 반려가 될 것이다
즉 우리가 사용하는 cpu 는 이 사실을 모른다는 것이다. 단지 랜카드가 "우리 찾는데?" 라고 이야기하면 cpu 는 "통신 준비할게" 할 뿐이다.
다시말해 cpu 낭비가 없는 통신 방법이다
맥 주소를 통해 타겟 기기과 소통하는 유니 캐스트와는 달리, 네트워크에 있는 모든 기기에게 메세지를 보내는 것을 브로드 캐스트라고 한다
유니캐스트에서는 맥 주소 검증을 통해 메세지를 수신할지 말지를 결정할 수 있었다면, 브로드캐스트는 그냥 모든 메세지를 다 받아야한다
네트워크 상 모든 기기에게 메세지를 보내다 보니 네트워크 오버헤드가 크고, 브로드캐스트 통신이 잦으면, 각 기기들의 cpu 들의 효율성이 떨어진다.
안내방송 쯤으로 생각하면 쉬운데, 일하다가 안내방송이 나오면 일하는 것을 멈추고 듣곤한다. 여기서 일하는 주체는 cpu 이고, 안내방송은 브로드캐스트 이다
그런데, 맥 주소를 설명하면서 말했듯 맥 주소는 단번에 알 수 없고, ARP 과정을 거쳐서 알 수 있다고 했다.
여기서 ARP 가 최초로 맥 주소를 찾아낼 때 쓰는 방식이 브로드 캐스트이다
예를들어 127.0.0.1 이 상대방 목적지 IP 이면, 라우터를 통해 127.0.0 대역에 있는 모든 기기들에게 "127.0.0.1 IP 주소 가진 사람 맥 주소좀 주세요" 라고 요청해서 맥 주소를 얻어낸다
브로드캐스트는 같은 네트워크에서 메세지를 보낼 의도가 없는 기기도 메세지를 받는다는 단점이 있다
그렇다고 유니캐스트로 보내자니 만약 메세지를 보내고 싶은 기기가 20개 있다면? (네트워크에는 100개의 기기가 있다고 가정)
20번의 네트워크 요청이 생기니 이거 나름대로 또 오버헤드가 커진다
그렇다면 특정 메세지를 수신할 의향이 있는 그룹을 만들어서 관리한다면?
즉 그룹에 가입한 기기들은 메세지를 받고, 나머지는 또 cpu 도달 전에 반려가 된다면, 효율적일 것이다
그것을 가능하게 하는 것이 멀티 캐스트
이다
멀티 캐스트 그룹 가입은 socket 옵션을 설정해주면 되는데, 그룹에 가입함과 동시에 해당 소켓이 멀티 캐스트의 메세지를 처리하겠다는 의미가 된다
멀티 캐스트 그룹에 등록하는 과정은 IGMP 프로토콜을 통해서 진행되는데,
우선 멀티 캐스트 라우터라는 특수 목적 라우터가 존재한다
이 라우터가 연결된 서브넷에 IGMP Query Message 를 주기적으로 보내는데, "혹시 멀티 캐스트 그룹에 가입하는 호스트 있어?" 라고 묻는 것이다.
주기 사이에 특정 호스트가 멀티 캐스트 그룹에 가입하였으면, IGMP Report Message 를 통해 멀티 캐스트 라우터에 보고를 한다.
이제 다음 부터는 멀티 캐스트 라우터를 통해 들어온 패킷을 분석해서 그룹 번호에 가입된 서브넷에 데이터를 전송하는 것이 멀티 캐스트의 전반적인 과정이다
초기에 멀티캐스트를 통한 불필요한 트래픽 (= 브로트캐스트에서 발생할 수 있는) 을 줄이고자 만들어진 방식도 여전히 비효율적이였다.
왜냐하면 멀티캐스트 그룹에 속하는 호스트의 정보를 서브넷에서 따로 저장하고 있지 않아, 매번 멀티캐스트 요청이 오면 그룹에 포함되는지에 대한 질의를 브로드캐스트로 서브넷에서 수행해서 불필요한 트래픽이 발생했기 때문이다
이를 방지하기 위해서, 스위치(L2) 선에서 그룹에 속하는 호스트의 주소(Mac) 테이블을 유지함으로써 이러한 문제를 해결했다
여기서 특이한 점은 멀티 캐스트 라우터는 서브넷을 저장하고 있다는 것이고, 그룹에 대한 정보는 서브넷에서 다루고 있는 것인데, 이와 같은 구조를 통해서 멀티 캐스트 라우터는 하나의 라우터와 통신을 하는 듯한 단순한 구조를 만들었다
struct ip_mreq join_adr;
join_adr.imr_multiaddr.s_addr = "멀티캐스트 그룹의 주소정보";
join_adr.imr_interface.s_addr = "그룹에 가입할 호스트의 주소정보";
setsockopt(recv_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(void*)&join_adr, sizeof(join_adr));
멀티 캐스트 가입에 사용되는 프로토콜 레벨은 IPPROTO_IP 이고
프로토콜 이름은 IP_ADD_MEMBERSHIP 이다
IP 레벨의 IP_ADD_MEMBERSHIP 속성
또한 TTL(Time To Live) 가 존재해야하는데, 멀티캐스트 자체가 라우터를 거쳐 가면서 "이 그룹 멤버 있어요?" 하는 거라서, 몇 개의 라우터를 거치면서 물어볼지를 정해야한다 (기본값은 1로, 로컬 네트워크에서 질의한다)
int time_live = 6;
setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL,
(void*)&time_live, sizeof(time_live));
IP 레벨의 IP_MULTICAST_TTL 속성
우리가 사용하는 라우터가 멀티 캐스트를 지원해 주어야하는데, 라우터가 그룹을 분별할 수 있어야지만 해당 그룹의 멤버들에게 메세지를 전달할 수 있다.
만약 지원하지 않는다면 브로드캐스트 형식으로 메세지가 전송된다