Netty 기본 예제
테스트 환경
Discard 서버
- 8888 port를 listen하는 web server. 데이터를 받기만 할 뿐 아무런 동작도 하지 않음.
- port와 handler를 설정하는 main server
- client로부터 받은 입력 데이터를 처리하는 handler
telnet localhost 8888
명령어로 테스트 가능
public class DiscardServer {
public static void main(String[] args) throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast(new DiscardServerHandler());
}
});
ChannelFuture future = bootstrap.bind(8888).sync();
future.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
}
public class DiscardServerHandler extends SimpleChannelInboundHandler<Object> {
private static final Logger logger = LoggerFactory.getLogger(DiscardServerHandler.class);
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception {
logger.debug("channelRead0");
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
logger.error("exceptionCaught", cause);
ctx.close();
}
}
Echo 서버, 클라이언트
- 서버는 입력 받은 메세지를 그대로 다시 클라이언트에게 돌려줌
- SimpleChannelInboundHandler 대신에 ChannelInboundHandlerAdapter 사용
- 클라이언트는 채널이 활성화되면 "Hello, Netty!" 메세지를 서버에게 전송
Server
public class EchoServer {
private static final Logger logger = LoggerFactory.getLogger(EchoServer.class);
private EventLoopGroup bossGroup;
private EventLoopGroup workerGroup;
private ServerBootstrap bootstrap;
public EchoServer() {
bossGroup = new NioEventLoopGroup(1);
workerGroup = new NioEventLoopGroup();
bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast(new EchoServerHandler());
}
});
}
public void start(final int port) throws InterruptedException {
logger.info("start server...");
ChannelFuture future = bootstrap.bind(port).sync();
future.channel().closeFuture().sync();
}
public void close() {
logger.info("close server...");
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
private static final Logger logger = LoggerFactory.getLogger(EchoServerHandler.class);
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
logger.debug("receive message \"{}\"", ((ByteBuf)msg).toString(Charset.defaultCharset()));
ctx.write(msg);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
logger.error("exceptionCaught", cause);
ctx.close();
}
}
Client
public class EchoClient {
private static final Logger logger = LoggerFactory.getLogger(EchoClient.class);
private EventLoopGroup group;
private Bootstrap bootstrap;
public EchoClient() {
group = new NioEventLoopGroup();
bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast(new EchoClientHandler());
}
});
}
public void connect(final String host, final int port) throws InterruptedException {
logger.info("connect to {}:{}", host, port);
ChannelFuture future = bootstrap.connect(host, port).sync();
future.channel().closeFuture().sync();
}
public void close() {
logger.info("close client...");
if (group != null) {
group.shutdownGracefully();
}
}
}
public class EchoClientHandler extends ChannelInboundHandlerAdapter {
private static final Logger logger = LoggerFactory.getLogger(EchoClientHandler.class);
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
String sendMessage = "Hello, Netty!";
ByteBuf messageBuffer = Unpooled.buffer();
messageBuffer.writeBytes(sendMessage.getBytes());
ctx.writeAndFlush(messageBuffer);
if (logger.isDebugEnabled()) {
logger.debug("send message \"{}\"", sendMessage);
}
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (logger.isDebugEnabled()) {
logger.debug("receive message \"{}\"", ((ByteBuf) msg).toString(Charset.defaultCharset()));
}
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.close();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
logger.error("exceptionCaught", cause);
ctx.close();
}
}