ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Netty TCP 서버 구축 실습
    Project 2024. 10. 9. 12:19

    Netty란?

    • 비동기 이벤트 기반 네트워크 애플리케이션 프레임워크

    TCPServer.java

    public class TCPServer {
    
        // 클라이언트의 요청을 받을 포트
        private final int port;
    
        public TCPServer(int port) {
            this.port = port;
        }
    
        public void start() throws InterruptedException {
            // 클라이언트의 연결 요청 처리
            NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
    
            // 데이터 입출력 처리
            NioEventLoopGroup workerGroup = new NioEventLoopGroup();
    
            try {
                // 네티 서버를 설정하고 시작하기 위한 도구 클래스
                ServerBootstrap sbs = new ServerBootstrap();
    
                // parent group, child group
                sbs.group(bossGroup, workerGroup)
    
                        // 서버가 사용할 채널 유형 설정 (Non-blocking IO)
                        .channel(NioServerSocketChannel.class)
    
                        // 새로운 클라이언트가 연결될 때마다 각 클라이언트 소켓에 대해 처리할 핸들러 설정
                        .childHandler(new ChannelInitializer<SocketChannel>() {
    
                            // 클라이언트가 연결될 때 호출되며, 각 클라이언트 연결마다 SocketChannel이 생성
                            @Override
                            protected void initChannel(SocketChannel socketChannel) {
                                ChannelPipeline pipeline = socketChannel.pipeline();
    
                                // 바이트 데이터를 문자열로 변환하는 디코더. 클라이언트로부터 받은 데이터를 문자열로 변환
                                pipeline.addLast(new StringDecoder());
    
                                // 서버에서 클라이언트로 보낼 데이터를 문자열에서 바이트로 변환하는 인코더. 네트워크에서 전송 가능한 형식으로 데이터를 변환
                                pipeline.addLast(new StringEncoder());
    
                                // 직접 정의한 핸들러 등록 (데이터를 처리하고 응답을 보내는 역할)
                                pipeline.addLast(new TCPServerHandler());
                            }
                        });
    
                // 클라이언트 연결 요청 대기
                ChannelFuture cf = sbs.bind(port).sync();
    
                // 서버가 종료될 때까지 대기
                cf.channel().closeFuture().sync();
            } finally {
                // 서버가 종료될 때 사용 중인 스레드를 안전하게 종료하고 자원을 정리
                bossGroup.shutdownGracefully();
                workerGroup.shutdownGracefully();
            }
        }
    
        public static void main(String[] args) throws InterruptedException {
            new TCPServer(8080).start();
        }
    }

     

     

    TCPServerHandler.java

    // ChannelInboundHandlerAdapter: 네티의 기본 핸들러로서, 수신된 데이터를 처리하는 데 사용
    public class TCPServerHandler extends ChannelInboundHandlerAdapter {
    
        /*
        클라이언트가 데이터를 서버로 전송했을 때 호출
        msg: 클라이언트로부터 받은 메시지
         */
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) {
            System.out.println("Received: " + msg);
    
            // 클라이언트에게 받은 메시지를 "Echo: "와 함께 다시 보냄
            ctx.writeAndFlush("Echo: " + msg);
        }
    
        /*
        통신 중에 예외가 발생했을 때 호출
        예외 상황을 로그로 출력하고, 클라이언트와의 연결을 닫음
         */
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            cause.printStackTrace();
            ctx.close();
        }
    }

    실행 결과