IT/java

[자바] netty 사용 방법

generator 2024. 7. 15. 10:10

kcb와의 통신을 위해서  netty를 처음 사용해 보았다.

좌충우돌이 많았지만 무사히 잘 마무리가 되었다.

서버에서 euc-kr을 사용해서 그와 관련된 처리 부분에서 시간을 많이 허비했다.

한글을 바이트 단위로 쪼개는 게 평소에는 잘하지 않는 부분이라 시간이 걸렸다.

별거 없는 내용이지만 이렇게 적어 두지 않으면 나중에 또 시간을 허비할게 뻔해서 최대한 틀만 살려서 내용을 기록해 둔다.

혹시나 netty를 사용하실 분에 도움이 되었으면 좋겠다.

 

import java.io.UnsupportedEncodingException;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
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.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import lombok.extern.slf4j.Slf4j;

public class TestService {
	
	public static final String ENCODING             = "EUC-KR";
	public static final Charset ENCODE              = Charset.forName(ENCODING);
	
	//네티 세팅
    public void runApi() throws Exception {
    	
        EventLoopGroup group = new NioEventLoopGroup();
		
        try {
            Bootstrap bootstrap = new Bootstrap();            
            bootstrap.group(group)
                     .channel(NioSocketChannel.class)
                     .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, "5000")
                     .handler(new ChannelInitializer<SocketChannel>() {
                         @Override
                         protected void initChannel(SocketChannel ch) throws Exception {
                             ChannelPipeline pipeline = ch.pipeline();
                             pipeline.addLast(new StringDecoder(ENCODE));
                             pipeline.addLast(new StringEncoder(ENCODE));
                             pipeline.addLast(new NettyClientHandler());
                         }
                     });
            ChannelFuture channelFuture = bootstrap.connect(new InetSocketAddress("host", "port")).sync();
            NettyClientHandler clientHandler = (NettyClientHandler) channelFuture.channel().pipeline().last();
            clientHandler.init(this);                        
            channelFuture.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully();
        }
    }
    
    
    // 서버와 통신을 담당하는 핸들러
    @Slf4j
    static class NettyClientHandler extends ChannelInboundHandlerAdapter  {
    	
    	TestService test;
    	private ChannelHandlerContext ctx;
    	
        
        private void init( TestService    test) throws Exception {    		
    		this.test          = test;
    		sendRequest("send msg");
    	}
    	
        // 서버로부터 받은 응답 처리    	
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object message) throws Exception {
    		
            //전달 받은 내용
            log.info((String)message);
			
            //총 길이
            int totTextLength = msg.getBytes(Charset.forName("EUC-KR")).length;			
            log.info(totTextLength);
    		
            //바이트 단위로 자르기
            String = kcb.substringEucKr((String)message,1,3);
        }
		
		
    	//메시지 전송
        public void sendRequest(String request) throws Exception {
        	
            byte[] strByte = request.getBytes("euc-kr");
            String strEuckr = new String(strByte,"euc-kr");
        	
            ChannelFuture fu = ctx.writeAndFlush(strEuckr).sync();
            fu.addListener(new ChannelFutureListener(){
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    if(future.isSuccess()) {
                         log.info("sendRequest() success!!");
                    }else {
                        log.info("sendRequest() fail!!");
                        future.cause().printStackTrace(System.err);
                        System.err.flush();
                    }
                }
            });
        }
        
        @Override
        public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
            log.info("channelReadComplete!!");
            ctx.flush();
        }
        
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            //출력
        	log.info("exceptionCaught!!"+cause);   
        	log.error(cause.getMessage());
        	log.error(cause.toString());
        	cause.printStackTrace();
        	cause.fillInStackTrace();
        	cause.getStackTrace();
        	System.out.flush();
        	ctx.close();
        }
        
        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            log.info("channelActive!!");
            this.ctx = ctx;
        }
        
        @Override
        public void channelInactive(ChannelHandlerContext ctx) throws Exception {
            log.info("channelInactive!!");
            this.ctx = ctx;
        }
        
        @Override
        public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
            log.info("channelRegistered!!");
        }

        @Override
        public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
            log.info("channelUnregistered!!");
        }
        
        @Override
        public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
            log.info("channelWritabilityChanged!!");
        }
        
        @Override
        public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
            log.info("userEventTriggered");
        }        
    }
    
    public static String substringEucKr(String str, int start, int end)  { 
   	 
        byte[] bytes = null;
        try {
             bytes = str.getBytes("EUC-KR");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } 
 
        byte[] subBytes = new byte[end - start]; 
        System.arraycopy(bytes, start, subBytes, 0, end - start); 
 
        try {
             return new String(subBytes, "EUC-KR");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return ""; 
    }
    
}