Netty Server
1. Maven Depedency 추가
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.16.Final</version>
</dependency>
</dependencies>
Netty 라이브러리를 이용하기 위한 디펜던시를 추가합니다.
2. Server
Netty 서버를 구성하기 위해 3가지 기초 설정이 필요합니다.
EventLoopGroup 생성과 ServerBootstrap 생성 및 구성, ChannelInitializer 생성입니다.
public class NettyServer {
public NettyServer() throws InterruptedException {
EventLoopGroup group = new NioEventLoopGroup();
try{
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(group);
serverBootstrap.channel(NioServerSocketChannel.class);
serverBootstrap.localAddress(new InetSocketAddress("localhost", 9999));
serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new ServerHandler()); // 핸들러 설정
}
});
ChannelFuture channelFuture = serverBootstrap.bind().sync();
channelFuture.channel().closeFuture().sync();
} catch(Exception e){
e.printStackTrace();
} finally {
group.shutdownGracefully().sync();
}
}
}
EventLoopGroup 생성
Netty TCP 서버를 만드는 첫 번째 단계로, EventLoopGroup을 생성해야합니다.
Netty는 Java NIO 를 사용하므로 NioEventLoopGroup이 생성됩니다.
ServerBootStrap 만들기
먼저 ServerBootstrap 인스턴스를 생성하고, 위 부트스트랩에 EventLoopGroup를 설정합니다.
그다음 NioServerSocketChannel클래스 인스턴스를 ServerBootstrap의 인스턴스로 설정합니다.
마지막으로 로컬 IP주소 또는 도메인 + TCP 포트로 InetSocketAddress를 설정합니다.
ChannelInitializer 생성
위에서 설정한 serverBootstrap에 자식 핸들러로 childHandler() 메서드를 호출 합니다.
이때, ChannelInitializer()를 생성해서 추상화된 initChannel()를 Override해줍니다.
이 함수의 인자인 SocketChannel을 통해 pipeline()을 생성하고, 이 파이프라인을 통해 들어오는 데이터를 처리하기 위한 핸들러를 붙혀줍니다.
여기서는 HelloServerHandler()를 생성해서 연결해주었습니다.
3. Server측 Handler
public class ServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf inBuffer = (ByteBuf) msg;
String received = inBuffer.toString(CharsetUtil.UTF_8);
System.out.println("Server received: " + received);
ctx.write(Unpooled.copiedBuffer("Hello " + received, CharsetUtil.UTF_8)); // 버퍼에 쓰기
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)
.addListener(ChannelFutureListener.CLOSE); // 채널 파이프라인에 저장된 버퍼 전송
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
Handler는 클라이언트 연결에서 들어오는 데이터를 처리하는 클래스입니다.
소켓 채널을 통해 데이터가 수신 될 때마다 channelRead() 메서드가 호출됩니다.
이때 서버 핸들러 측에서는 ChannelHandlerContext를 통해 데이터를 버퍼에 써서 반환해줍니다.
channelReadComplete()는 소켓 채널로부터 읽을 수 있는 데이터가 더 이상 존재하지 않을 때 호출되는데, 마지막으로 채널을 닫아주는 역할을 합니다.
exceptionCaught()는 수신 또는 데이터를 전송하는 동안 예외가 발생하는 경우에 불려집니다.
여기에서 연결을 닫거나 오류 코드로 응답하는 등 어떤 일이 발생해야하는지 결정할 수 있습니다.
참고 사이트
http://tutorials.jenkov.com/netty/netty-tcp-server.html
'프로토콜 > Netty' 카테고리의 다른 글
[Java] Netty Client (0) | 2020.09.07 |
---|---|
Netty 파이프라인 (0) | 2020.09.04 |
Netty란? (0) | 2020.09.01 |