가. 준비사항
- Netty최신 버젼
- jdb1.5 혹은 그 이상 버젼
나. Netty 프로젝트 커뮤니티
- http://www.jboss.org/netty/community.html
2. Discard 서버 작성하기
- Discard 프로토콜을 구현하기 위해서는 단지 수신된 데이터를 로깅하기만 하면 된다.
@
ChannelPipelineCoverage
("all")public class DiscardServerHandler extends
SimpleChannelHandler
{@Override
public void messageReceived(
ChannelHandlerContext
ctx, MessageEvent
e) {}
@Override
public void exceptionCaught(
ChannelHandlerContext
ctx, ExceptionEvent
e) {e.getCause().printStackTrace();
Channel
ch = e.getChannel();ch.close();
}
}
Channel
(그리고 채널과 관련된 ChannelPipeline
)에 의해 공유될 수 있는지를 알려주기 위해 어노테이트 선언을 한다.DiscardServerHandler는 어떤 상태 유지 정보도 다루지 않기때문에 "all" 값으로 어노테이트 되었다.
DiscardServerHandler
extends SimpleChannelHandler
는 오버라이드 가능한 다양한 이벤트 핸들러 메소드를 제공하는
ChannelHandler
. SimpleChannelHandler
의 구현체이다. 현재로서는 스스로 핸들러인터페이스를 구현하는것 보다
SimpleChannelHandler
를 상속받는것으로도 충분하다.여기서는 messageReceived 이벤트 핸들러 메소드를 오버라이드 했다. 이 메소드는 클라이언트로부터
새로운 데이터가 수신될때마다, 수신된 데이터를 포함하는
MessageEvent
와 함께 불리어진다. 위 예제에서 Discard 서버를 구현하기 위해서 아무 처리를 하지 않음으로써 수신 데이터를 무시한다.
I/O에러에 의해 Netty 에서 혹은 이벤트를 처리할동안 핸들러 구현에 의해 exception 이 발생할 때
ExceptionEvent
와 함께 exceptionCaught
이벤트 핸들러 메소드가 호출 된다. 대부분의 경우에 exception은 로깅되며, 여러분이 예외 상황을 원하는데로 처리할 수 있을지라도 여기서 관련 채널은 클로즈 되어져야 한다.예를들어 연결을 닫기 전에 에러코드를 포함한 응답메세지를 보낼 수 있다.이제는 DiscardServerHandler를 가지고 서버를 작성해 보자
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
public class DiscardServer {
public static void main(String[] args) throws Exception {
ChannelFactory
factory =new
NioServerSocketChannelFactory
(Executors.newCachedThreadPool(),
Executors.newCachedThreadPool());
ServerBootstrap
bootstrap = new ServerBootstrap
(factory);DiscardServerHandler handler = new DiscardServerHandler();
ChannelPipeline
pipeline = bootstrap.getPipeline();pipeline.addLast("handler", handler);
bootstrap.setOption("child.tcpNoDelay", true);
bootstrap.setOption("child.keepAlive", true);
bootstrap.bind(new InetSocketAddress(8080));
}
}
|
ChannelFactory
구현을 제공한다. 위 예제 코드는 서버측 어플리케이션을 구현한 것이고, 그래서 NioServerSocketChannelFactory
가 사용되었다. 주목해야 할 또다른 것은 Channel Factory 는 스스로 I/O 쓰레드를 생성하지 않는다는 것이다. channelFactory 는 컨스트럭터에서 명시한 쓰레드 풀로부터 쓰레드를 획득하고 보안관리가 필요한 어플리케이션과 같은 , 어플리케이션 운영환경에서 쓰레드를 다루는 방법에 대한 보다 많은 제어를 제공한다. ServerBootstrap
는 서버를 설정하기 위한 헬퍼 클래스이다. 여러분은 직접 채널을 이용하는 서버를 설정할 수 있다. 하지만 이것은 지루한 과정이며 대부분의 경우에는 이런 설정을 할 필요가 없다.
위 소스에서 DiscardServerHandler 를 디폴트 ChannelPipeline
. 에 추가하였다. 서버에 새로운 커넥션이 어셉트 될때마다 어셉트 되는 채널을 위해 ChannelPipeline
. 이 생성되고 여기서 추가된 모든 ChannelHandler
s는 새로운 ChannelPipeline
. 에 추가될것이다.이것은 얕은 복사(Shallow-copy)동작과 유사하다. 모든 채널과 채널파이프라인은 같은 DiscardServerHandler 인스턴스를 공유할 것 이다.
Channel
구현에 패러미터를 설정할 수 있다. 우리는 TCP/IP 서버 프로그램을 작성하고 있어서 채널 구현에 tcpNoDelay 와 keepAlive
. 와 같은 소켓 옵션을 설정할 수 있다. 모든 옵션에 "child." 프리픽스를 추가하는걸 명심해야 한다. 이것은 ServerSocketChannel
의 옵션이 아닌 어셉트된 채널에 적용된다는 것을 의미한다. 서버소켓채널의 옵션 설정은 아래와 같이 설정 가능하다.
bootstrap.setOption("reuseAddress", true);
이제 포트를 바인드 하고 서버를 기동하는 것만 남았다. Nics(network interface cards) 에 8080포트로 바인드 한다.
3. 서버 테스트 하기
테스트 하기 가장 쉬운 방법은 telnet 명령어를 사용하는 것이다. 커맨드 라인에 "telnet localhost 8080" 입력하고 문자를 입력한다. 서버를 잘 작동하는가? 서버가 디스카드 서버이기 때문에 실제로 잘 동작하는지 파악하기 힘들다. 그래서 수신된 값을 프린트 하도록 변경해보자.
이미 우리는 데이터가 수신될때마다 MessageEvent 만들어지고 messageReceived 핸들러 매소드가 호출된다는 것을 알고 있다. DiscardServerHandler 의 messageReceive 메소드에 몇줄의 코드를 집어넣어보자.
public void messageReceived(
ChannelHandlerContext
ctx, MessageEvent
e) {ChannelBuffer
buf = (ChannelBuffer) e.getMessage();while(buf.readable()) {
System.out.println((char) buf.readByte(i));
}
}
소켓 전송에서 메세지 타입은 항상 ChannelBuffer
. 라고 가정하는게 확실하다. 채널버퍼는 Netty 에서 일련의 바이트들을 저장하는 기본적인 데이터 구조체이다. 이것은 NIO ByteBuffer 와 유사하지만 사용하기 쉽고 보다 유연하다.
예를들어 Netty 는 불필요한 메모리 카피의 수를 줄이기 위한 다중 ChannelBuffer 결합하는 복합 ChannelBuffer 를 생성하는것을 허용한다.
비록 NIO ByteBuffer 를 많이 닮았지만 ,API를 참조하는 것을 추천한다. 채널버퍼(ChannelBuffer
)의 올바른 사용 방법을 배우는 것은 어려움 없이 Netty를 사용하기 위한 중요한 단계이다.
references
http://www.jboss.org/file-access/default/members/netty/freezone/guide/3.0/html_single/index.html
출처: http://run4dream.tistory.com/entry/1-Netty-를-이용하여-프로그램하기