Quote of the Moment UDP/IP 브로드캐스트 예제
기존에 예제들 처럼 1:1 통신이 아니라 브로드캐스트 통신 예제이다.
우선 클리이언트를 살펴보면
파이프라인팩토리를 설정하는 것은 그다지 특이하지 않다.
QuoteOfTheMomentClientHandler를 살펴보면 될듯 하다.
받은 메시지들 중에 QOTM을 시작하하는 것이 있으면 이를 출력하고 연결을 종료한다.
이제 서버측 프로그램을 살펴보자.
서버측은 클라이언트측과 거의 동일한데 차이점은 등록할 핸들러가 다르다는것과 8080 포트를 바인딩한다는 것이다.
연결형 통신과 다르게 write 함수 호출할 때 전달할 대상의 주소를 전달한다. channel은 연결되어 있는 상태가 아니므로 채널에 주소 없이 write 하면 안된다.
기존에 예제들 처럼 1:1 통신이 아니라 브로드캐스트 통신 예제이다.
우선 클리이언트를 살펴보면
49 ConnectionlessBootstrap b = new ConnectionlessBootstrap(f);
62 b.setOption("broadcast", "true");
ClientBootstrap 이 아니라 ConnectionlessBootstrap을 사용하고 있다.ConnectionlessBootstrap은 UDP/IP와 같은 연결지속성이 없는 네트워크를위해 사용된다. 그리고 브로드캐스트 형태로 통신하도록 옵션을 설정했다.
74 b.setOption( 75 "receiveBufferSizePredictorFactory",
76 new FixedReceiveBufferSizePredictorFactory(1024));
UDP는 버퍼사이즈보다 더 큰 패킷을 받는 경우 짤라내거나 드랍시켜버릴 수 있다. 일단 여기서는 1024로 지정했다. 그러나 라우터 옵션에 따라 일정 사이즈 이상으로 보내면 패킷이 소실될 수 있다.
78 DatagramChannel c = (DatagramChannel) b.bind(new InetSocketAddress(0)); 79 80 // Broadcast the QOTM request to port 8080. 81 c.write("QOTM?", new InetSocketAddress("255.255.255.255", 8080));
브로드캐스트를 위해 255.255.255.255 로 패킷을 전송한다.
86 if (!c.getCloseFuture().awaitUninterruptibly(5000)) {
87 System.err.println("QOTM request timed out.");
88 c.close().awaitUninterruptibly();
89 }
5초안에 연결 종료가 되지 않으면 에러메시지를 출력하고 접속을 종료한다.
45 DatagramChannelFactory f = 46 new NioDatagramChannelFactory(Executors.newCachedThreadPool());채널 팩토리도 기존에 NioClientSocketChannelFactory 또는 NioServerSocketChannelFactory와 다르게 하나의 Executor만을 사용하는 NioDatagramChannelFactory를 사용한다. 이는 연결 지속형이 아니므로 boss와 work 쓰레드가 따로 필요없어서 인듯 하다.
52 b.setPipelineFactory(new ChannelPipelineFactory() { 53 public ChannelPipeline getPipeline() throws Exception { 54 return Channels.pipeline( 55 new StringEncoder(CharsetUtil.ISO_8859_1), 56 new StringDecoder(CharsetUtil.ISO_8859_1), 57 new QuoteOfTheMomentClientHandler()); 58 } 59 });
파이프라인팩토리를 설정하는 것은 그다지 특이하지 않다.
QuoteOfTheMomentClientHandler를 살펴보면 될듯 하다.
30 @Override 31 public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) 32 throws Exception { 33 String msg = (String) e.getMessage(); 34 if (msg.startsWith("QOTM: ")) { 35 System.out.println("Quote of the Moment: " + msg.substring(6)); 36 e.getChannel().close(); 37 } 38 }
받은 메시지들 중에 QOTM을 시작하하는 것이 있으면 이를 출력하고 연결을 종료한다.
이제 서버측 프로그램을 살펴보자.
서버측은 클라이언트측과 거의 동일한데 차이점은 등록할 핸들러가 다르다는것과 8080 포트를 바인딩한다는 것이다.
50 @Override 51 public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) 52 throws Exception { 53 String msg = (String) e.getMessage(); 54 if (msg.equals("QOTM?")) { 55 e.getChannel().write("QOTM: " + nextQuote(), e.getRemoteAddress()); 56 } 57 }
연결형 통신과 다르게 write 함수 호출할 때 전달할 대상의 주소를 전달한다. channel은 연결되어 있는 상태가 아니므로 채널에 주소 없이 write 하면 안된다.