hyuko

네티 서버 구현 본문

Springboot

네티 서버 구현

hyuko12 2024. 7. 19. 09:46
728x90
반응형

- 기본 설정 클래스 NettyConfig 구성

 

@Configuration
@RequiredArgsConstructor
public class NettyConfig {

    @Bean
    public ServerBootstrap serverBootstrap(ServerChannelInitializer serverChannelInitializer) {
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(bossGroup(), workerGroup()).channel(NioServerSocketChannel.class).childHandler(serverChannelInitializer);
        return serverBootstrap;
    }

    @Bean(destroyMethod = "shutdownGracefully") // 스프링 컨테이너가 종료될 때 해당 메서드가 호출되도록 한다.
    public NioEventLoopGroup bossGroup() {
        return new NioEventLoopGroup(1); // 들어오는 연결을 수락하는 역할 거기서 사용 될 스레드의 수를 정함.
    }

    @Bean(destroyMethod = "shutdownGracefully")
    public NioEventLoopGroup workerGroup() {
        return new NioEventLoopGroup(); // 연결된 클라이언트와 데이터 통신을 처리하는 역할
    }
}

 

- Netty Chanel 구현

@Component
@RequiredArgsConstructor
public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {

		private final ServerHandler serverHandler;

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
				ChannelPipeline pipline = ch.pipline();
				Decoder decoder = new Decoder();
				Encoder encoder = new Encoder();
				
				pipline.addLast(decoder, encoder, serverHandler);
    }
}

- ChannelInitializer를 통해서 SocketChannel 을 주입합니다.

- initChannel 메소드에서 Channel Pipline을 구성한다.

- pipline에 추가될 것들로는 decoder, encoder, handler 순으로 들어간다.

 

Decoder

public class Decoder extends ByteToMessageDecoder {
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        // 여기서 in은 들어오는 메시지 받을 바이트의 길이를 정해줍니다.
				ByteBuf response = in.readBytes(length);
				// 읽기 편하게 byte[]로 변환한다.
				byte[] responseData = new byte[response.readableBytes()];
				response.readBytes(responseData);

				out.add(responseData); //  여기서 out에 저장하면 handler에서 읽을 수 있습니다.
				response.release(); // 버퍼해제는 꼭 해주어야 한다.
    }
}

- 디코더에서는 들어오는 메시지를 조건을 주어서 통과를 시킬지 선택할 수 있다.

- 메시지를 파싱하는 것을 미리 한 후 그 다음 파이프라인인 handler에 전달할 수 있다.

 

Encoder

public class Encoder extends MessageToByteEncoder<byte[]> {

    @Override
    protected void encode(ChannelHandlerContext ctx, byte[] msg, ByteBuf out) throws Exception {
        out.writeBytes(msg);
    }
}

 

Handler

@Component
@RequiredArgsConstructor
@ChannelHandler.Sharable //  해당 어노테이션을 붙이게 되면 여러 채널에서 핸들러 인스턴스를 공유할 수 있음을 나타낸다.
public class ServerHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
				// 채널이 연결되어 활성화 상태일 때 행동들을 정의
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
				// 디코더에서 out 리스트에 저장된 object값이 msg이다. 
    }

}

 

Netty 서버 시작

public class NettyServer{
		private final ServerBootstrap serverBootstrap;
		@Value("${application.yml}")
		private int port;
		public void startServer() {
			try {
            InetAddress inetAddress = InetAddress.getLocalHost(); 
            host = inetAddress.getHostAddress(); // 현재 로컬의 호스트주소 
        } catch (UnknownHostException e) {
            log.error(e.getMessage());
        }
        serverBootstrap.localAddress(new InetSocketAddress(host, port));
        ChannelFuture f = serverBootstrap.bind(); // 실질적인 서버 연결

        f.addListener((ChannelFuture future) -> {
            if (future.isSuccess()) {
                log.info("Netty server started successfully on {}:{}", host, port);
            } else {
                log.error("Netty server failed to start", future.cause());
            }
        });

        f.channel().closeFuture();
		}

}

 

스프링 부트가 실행이 될 때 실행시키기 위해서 아래와 같이 정의한다.

 

@Component
@RequiredArgsConstructor
public class NettyApplicationStartupTask implements ApplicationListener<ApplicationReadyEvent> {

    private final NettyServer nettyServer;

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {

        nettyServer.startServer();

    }
}
728x90
반응형

'Springboot' 카테고리의 다른 글

Netty 클라이언트와 서버의 차이점  (0) 2024.07.19
Netty Client  (0) 2024.07.19
Netty  (0) 2024.07.19
spring security / 전체적인 흐름  (0) 2023.04.29
회원가입 / 로그인  (0) 2023.04.29