참고 :
첫 4개 비트가 1110인 주소
- 224.0.0.0 ~ 239.255.255.255
다른 IP 주소처럼 Multicast 주소도 호스트 이름을 가질 수 있다.
하나의 Multicast 주소를 공유하는 인터넷 호스트들의 집합
멀티캐스트를 수신하기 위해서는 멀티캐스트 그룹에 가입해야 한다. 그러나 그룹에 가입하지 않아도 데이터를 전송할 수는 있다.
Multicast 주소로 전송된 임의의 데이터는 그룹의 모든 멤버에게 배포 전달된다.
- Multicast 그룹에 호스트가 가입하고 탈퇴하는 것은 자유롭다.
현재 자바는 Multicast 그룹을 만들 수 있는 기능이 없지만, 그룹에 가입할 수 있는 클래스는 제공
IANA (Internet Assigned Number Authority) 에서 필요한 경우 영구 Multicast 주소 배부
MBONE -> 멀티캐스팅을 지원하는 라우터와 호스트로 이루어진 네트워크
예 : 영구히 지속되는 멀티캐스트 그룹의 주소
예 : TTL의 값에 따른 예상 전파 범위
동일한 라우터에 연결된 네 개의 클라이언트에 동일한 데이터를 전송했을 경우를 비교
멀티캐스팅에서 프로그래머의 역할
- 네트워크에서의 전달은 라우터가 전담한다.
byte[] data = "Here's some mulicast data\r\n".getBytes("UTF-8");
InetAddress group = InetAddress.getByName("experiment.mcast.net");
int port = 4000; // 데이터 수신을 기다리고 있는 UDP 포트
DatagramPacket dp = new DatagramPacket(data, data.length, group, port);
MulticastSocket ms = new MulticastSocket();
ms.send(packet);
try {
MulticastSocket ms = new MulticastSocket();
} catch (SocketException se) {
System.err.println(se);
}
MulticastSocket ms2 = new MulticastSocket(4000);
SocketAddress address = new InetSocketAddress("192.168.254.32", 4000);
MulticastSocket ms3 = new MulticastSocket(address);
- 소켓 생성 불가능 시에 SocketException 발생
- 루트 권한이 없이 1024 이하의 포트 사용을 시도하는 경우
- 연결하려는 포트를 다른 MulticastSocket 또는 DatagramSocket이 이미 사용 중일 경우
try{
MulticastSocket ms = new MulticastSocket(4000);
// 데이터를 읽어 올 multicast 주소
InetAddress ia = InetAddress.getByName("224.2.2.2");
// 그룹에 가입 -> 데이터 수신은 Unicast Datagram과 동일
ms.joinGroup(ia);
while(true) {
DatagramPacket dp = new DatagramPacket(data, data.length);
ms.receive(dp);
String s = new String(dp.getData(), "UTF-8");
System.out.println(s);
}
}catch(IOException ex) {}
MulticastSocket ms = new MulticastSocket();
SocketAddress group = new InetSocketAddress("224.2.2.2", 40);
NetworkInterface ni = NetworkInterface.getByName("eth0");
if (ni != null)
ms.joinGroup(group, ni);
else
ms.joinGroup(group);
public void leaveGroup(InetAddress mcastaddr) throws IOException
public void leaveGroup(SocketAddress mcastaddr, NetworkInterface interface) throws IOException
- Multicast 그룹으로부터 더 이상 데이터그램을 받지 않을 것임을 알림
MulticastSocket 클래스의 거의 모든 메소드는 IOException을 발생시키므로 보통 try 블록에서 호출
Java 7 에서는 DatagramSocket 클래스가 AutoCloseable 을 구현하고 있으므로 try-with-resource 사용 가능
예 : try-with-resource 사용
try(MulticastSocket ms = new MulticastSocket()) {
// 서버에 연결
}catch (IOException ex) {
ex.prinStackTrace();
}
예 : try-with-resource 미사용
try{
ms = new MulticastSocket() // 서버에 연결
} catch (IOException ex) {
ex.prinStackTrace();
} finally {
if (ms != null) {
try {
ms.close();
} catch (IOException ex) {
// 무시
}
} // if
} // finally
UDP Unicast 와 유사
- UDP Datagram 을 Multicast address 로 보낸다.
MulticastSocket() 생성자를 이용해 객체 생성
데이터를 보낼 때는 Multicast 그룹에 가입할 필요가 없다.
DaagramPacket 객체를 구성한다.
- <강조> 바이트 배열
MulticastSocket 의 send() 메소드 호출을 통해 데이터 송신
MulticastSocket 의 close() 메소드를 사용하여 소켓 종료
try {
InetAddress group = InetAddress.getByName("Experiment.mcast.net");
byte[] data = "Here's some multicast data\r\n".getBytes();
int port = 4000;
DatagramPacket dp = new DatagramPacket(data, data.length, group, port);
MulticastSocket ms = new MulticastSocket();
ms.sned(dp);
} catch(IOException ex) {
ex.prinStackTrace();
}
예 :
try{
InetAddress group = InetAddress.getByName("experiment.mcast.net");
bye[] data = "Here's some multicast data\r\n".getBytes();
int port = 4000;
DatagramPacket dp = new DatagramPacket(data, data.length, group, port);
MulticastSocket ms = new MulticastSocket();
ms.setTimeToLive(64);
ms.send(dp);
} catch(IOException ex) {
ex.prinStackTrace();
}
import java.io.*;
import java.net.*;
public class MulticastClient {
MulticastSocket socket = null;
DatagramPacket packet = null;
InetAddress group = null;
int port = 20001;
String address = "237.100.100.1";
byte[] b = new byte[100];
public MulticastClient() {
try {
socket = new MulticastSocket(port);
group = InetAddress.getByName(address);
packet = new DatagramPacket(b, b.length);
socket.joinGroup(group);
for (int i = 0; i < 3; i++) {
socket.receive(packet);
String notice = new String(packet.getData());
System.out.println(notice);
}
socket.leaveGroup(group);
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
new MulticastClient();
}
}
import java.io.*;
import java.net.*;
public class MulticastServer extends Thread {
DatagramSocket socket = null;
DatagramPacket packet = null;
InetAddress multicastGroup = null;
int port = 20001;
String address = "237.100.100.1";
boolean onAir = true;
public MulticastServer() throws IOException {
super("멀티캐스트 방송국");
socket = new DatagramSocket();
}
public void run() {
byte[] b = new byte[100];
while (onAir) {
try {
b = "이 자료는 멀티캐스트 방송국에서 보내고 있습니다".getBytes(); // 메시지를 바이트 배열로 변환
multicastGroup = InetAddress.getByName(address);
packet = new DatagramPacket(b, b.length, multicastGroup, port);
socket.send(packet);
try {
sleep(500);
System.out.println("방송 중입니다.");
} catch (InterruptedException e) { }
} catch (IOException e) {
e.printStackTrace();
}
} // end while
socket.close();
}
public static void main(String[] args) throws java.io.IOException {
new MulticastServer().start();
}
}
import java.io.*;
import java.net.*;
public class MulticastSniffer {
public static void main(String[] args) {
InetAddress group = null;
int port = 0;
// read the address from the command line
try {
group = InetAddress.getByName(args[0]);
port = Integer.parseInt(args[1]);
} catch (ArrayIndexOutOfBoundsException | NumberFormatException
| UnknownHostException ex) {
System.err.println(
"Usage: java MulticastSniffer multicast_address port");
System.exit(1);
}
MulticastSocket ms = null;
try {
ms = new MulticastSocket(port);
ms.joinGroup(group);
while (true) {
byte[] buffer = new byte[8192];
DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
ms.receive(dp);
String s = new String(dp.getData(), "UTF-8");
System.out.println(s);
}
} catch (IOException ex) {
System.err.println(ex);
} finally {
if (ms != null) {
try {
ms.leaveGroup(group);
ms.close();
} catch (IOException ex) {}
}
}
}
}
출력 예 :
M-SEARCH * HTTP/1.1
HOST: 239.255.255.250:1900
MAN: "ssdp:discover"
MX: 1
ST: urn:dial-multiscreen-org:service:dial:1
USER-AGENT: Google Chrome/54.0.2840.99 Windows
ectionManager:1
NTS: ssdp:alive
SERVER: Linux/2.x.x, UPnP/1.0, pvConnect UPnP SDK/1.0
USN: uuid:7076436f-6e65-1063-8074-001d737f3cef::urn:schemas-upnp-org:service:ConnectionManager:1
ediaReceiverRegistrar:1
.0
OPT:"http://schemas.upnp.org/upnp/1/0/"; ns=01
01-NLS:8cf259374f018f5b416893eea90e5a01
a90e5a01
eea90e5a01
import java.io.*;
import java.net.*;
import java.util.Date;
public class MulticastSender {
public static void main(String[] args) {
InetAddress ia = null;
int port = 0;
byte ttl = (byte) 1;
// command line에서 주소 읽어 들임
try {
ia = InetAddress.getByName(args[0]);
port = Integer.parseInt(args[1]);
if (args.length > 2) ttl = (byte) Integer.parseInt(args[2]);
} catch (NumberFormatException | IndexOutOfBoundsException
| UnknownHostException ex) {
System.err.println(ex);
System.err.println(
"Usage: java MulticastSender multicast_address port ttl");
System.exit(1);
}
try (MulticastSocket ms = new MulticastSocket()) {
ms.setTimeToLive(ttl);
ms.joinGroup(ia);
for (int i = 0; i < 10; i++) {
byte[] data = (i + " " + new Date() + " 멀티캐스트 데이터입니다\r\n").getBytes("UTF-8");
DatagramPacket dp = new DatagramPacket(data, data.length, ia, port);
ms.send(dp);
}
ms.leaveGroup(ia);
} catch (SocketException ex) {
System.err.println(ex);
} catch (IOException ex) {
System.err.println(ex);
}
}
}
MulticastSniffer 를 다음과 같이 실행시킨 상태에서