1. 기본 구조
netty의 가장 기본적인 코딩 구조이다.
DiscardServer.java
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
public class DiscardServer {
public static void main(String[] args) throws Exception {
Configurator.setLevel(DiscardServer.class.getName(), Level.ALL);
EventLoopGroup bossGroup = new NioEventLoopGroup(1); // 편의점 출입구
EventLoopGroup workerGroup = new NioEventLoopGroup(); // 편의점 내 카운터
try {
ServerBootstrap b = new ServerBootstrap(); // 편의점 가게
b.group(bossGroup, workerGroup); // 가게안에 출입구 달고, 카운터를 배치
b.channel(NioServerSocketChannel.class); // 통신방식
b.childHandler(new ChannelInitializer<SocketChannel>() { // 첫고객이 문열고 들어왔을때 어떻게 할까 결정(고객응대방법)
@Override
public void initChannel(SocketChannel ch) {
//logger.debug("편의점 손님 들어옴..");
ChannelPipeline p = ch.pipeline();
p.addLast(new DiscardServerHandler());
}
});
//logger.debug("편의점 열었음..");
ChannelFuture f = b.bind(8009).sync(); // 문열고 기다림
f.channel().closeFuture().sync(); // 문 닫을 때 까지 여기서 대기
} catch (Exception e) {
//logger.debug("편의점 오류남..{}", e.getMessage());
} finally {
//logger.debug("편의점 닫는 중..");
workerGroup.shutdownGracefully(); // 우선 카운터 닫고
bossGroup.shutdownGracefully(); // 편의점 닫고
//logger.debug("편의점 닫음..");
}
}
}
편의점으로 비교해볼까? 어울릴지 모르겠다
편의점을 열고 (ServerBootstrap) , 문을 달고 ( EventLoopGroup ), 카운터를 차리자 ( EventLoopGroup )
실제로 설명은 이렇게 되어 있다
ServerBootstrap
애플리케이션의 동작 및 설정을 지정해주는 헬퍼클래스, 근데 ServerBootstrap 이 있으면 Bootstrap도 있을것 같지?
맞다 있다. 서버용과 클라이언트 용이 있구나
ServerBootstrap.group
ServerBootstrap내에 보면 두개의 인자가 있다. parentGroup와 childGroup으로 나눠지는데
설명상보면 parentGroup은 연결을 담당하고, childGroup 데이터 전송을 담당한다고 한다.
EventLoopGroup에는 NioEventLoopGroup외에도 아래와 같이 많은 EventLoopGroup이 있다.
이런것들이 있다만 보고 나중에 필요할때 한번씩 챙겨보면 좋을 듯..
EpollEventLoopGroup, LocalEventLoopGroup, MultithreadEventLoopGroup, NioEventLoop, NioEventLoopGroup, OioEventLoopGroup, SingleThreadEventLoop, ThreadPerChannelEventLoop, ThreadPerChannelEventLoopGroup
ServerBootstrap.channel
서버가 어떤 통신방식을 할지 결정한다. EventLoopGroup에서 NioEventLoopGroup 를 사용했으니, NioServerSocketChannel.class를 사용한다.
위에서 언급한 다양한 EventLoopGroup이 있으니 나중에 어떻게 쓸지 고민해보자
ServerBootstrap.childHandler
손님이 들어온 뒤 해야할 일과 나갈때 해야할일들을 여기다 지정해 둔다.
순서는 어떻게 정할까? 다음코드를 보자
ChannelPipeline p = ch.pipeline();
파이프라인이다. 물이 흐르는 파이프라인으로 보면 해당 파이프 라인 첨부터 해서 끝까지 쭉 흐른다고 보면 될것같다.
addFirst, addLast, addAfter, addLast 요것들만 있으면 맘대로 내가 원하는데 꽂아 넣을수 있겠구나
ChannelHandler
이건 고객응대 메뉴얼 같은거라 보면 될것 같다. 외국인이면 누가 처리할래? 진상고객은 누가 처리할래?
이런식으로 손님이 들어왔으면 어떻게, 누가 처리할지를 pipeline에서 할당하고 직접처리해주는 곳이라고 보면 될듯
ChannelHandler는 ChannelInboundHandlerAdapter, ChannelOutboundHandlerAdapter 두개가 있다.
하나는 들어오는것, 하나는 나가는것이라고 이름만 봐도 알수가 있을것 같다.
요건 다시 다른장에서 설명해야할듯 하다
bind, ChannelFuture
bind는 일반 Socket 프로그램에서 많이 봤듯이, 자 포트번호(아래 8009)로 가계 문열고 기달리고 있을테니 들어올테면 들어와라.
라는 뜻이다
ChannelFuture f = b.bind(8009).sync(); // 문열고 기다림
ChannelFuture
이건 나도 첨에 나같은 쪼랩은 이해를 못했었는데 bind가 되고나면 바로 다음코드를 실행한다
그리고 f ( ChannelFuture)가 문이 닫힐때까지 대기하다가 문이 닫히면 바로 다음 코드로 넘겨준다.
f.channel().closeFuture().sync(); // 문 닫을때를 알기위해 여기서 대기 함
shutdownGracefully
생성된 EventLoopGroup을 닫는다..
workerGroup.shutdownGracefully(); // 우선 카운터 닫고
bossGroup.shutdownGracefully(); // 편의점 닫고
'프로그래밍 > Netty 기초' 카테고리의 다른 글
06. Discard Client 만들기 (0) | 2022.01.07 |
---|---|
04. ChannelHandler 란 (0) | 2022.01.06 |
05. channeInboundAdapter 이벤트 순서 (0) | 2022.01.06 |
01. Netty란 (0) | 2022.01.06 |
02. Discard 서버 (0) | 2022.01.06 |