Java재밌당
1k
2022-01-13 09:22:42 작성 2022-01-13 09:29:34 수정됨
5
146

Netty 관련 질문!


안녕하세요. 네티 관련 질문이 있어 남겨봅니다.!

과제는 전문 관련 요청 및 응답이구

지금은 로그인 인증을 시도하고 응답코드를 받으면, 그 이후에 로그인 인증 할 때

바디로 같이 던진 세션타입이 유지가 되는지 체크해주는

세션 체크 전문을 바로 날리고 있습니다.

그런데 날릴때마다 인셉션이 뜨면서 채널이 끊어지더라구요.

어느 부분이 문제일까요?.. 이번주 동안 계속 고쳐보고 있는데 어렵네요.

실행 과정은 첫번째 전문인 로그인 전문 날리고

응답코드를 받은 후, 로그인 인증이 된 채널을 통해

세션 체크 전문을 날려서 임의로 4자리 수를 넘겨주면 4자리 수가 다시 되돌아오는

에코서버 형태의 응답을 받아야 합니다.


핸들러 측 메세지 센드, 리시브 코드

    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        //Channel이 활성화됨(원격 피어로 연결됨). 이제 데이터를 주고받을 수 있음
        System.out.println("channelActive");

        //처음 채널이 활성화 되면 메시지 배열의 제일 첫 메시지를 보낸다..
        sendMsg(ctx, msgArr[idx++]);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        //Channel에서 데이터를 읽을 때 호출됨
        System.out.println("channelRead");
        //서버로부터 받은 메시지를 읽어서 변환한다..
        ByteBuf buf = (ByteBuf)msg;
        int readMessage = buf.readableBytes();
        if( readMessage > 0 ) {
            byte[] recvmsg = new byte[readMessage];
            buf.readBytes(recvmsg);
            //수신메시지 출력
            String receiveMsg = new String( recvmsg );
            System.out.println("receiveMsg : " + receiveMsg);

            if ( msgArr.length == idx ) {
                System.out.println("모든 메시지 전송 및 수신 완료");

            }
            else {
                sendMsg(ctx, msgArr[idx++]);
            }
        }
    }


메인 클래스 코드 

기능 구현을 우선적으로 두고 있어서 시간이 부족하여

아직 코드가 좀 미숙한점 죄송합니다. 

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.net.InetSocketAddress;
import java.net.SocketAddress;

public class NettyClient {
/*
네티에서 제공하는 편리한 팩토리 클래스(BootStrap)이며 Netty 클라이언트
측 또는 서버 측 Netty 초기화를 완료하는데 사용할 수 있습니다.
부트 스트랩 객체 생성
*/
private Bootstrap bs = new Bootstrap();

//접속할 서버의 host, port 정보가 담길 변수
private SocketAddress socketAddress;

//서버에 전송할 메시지 배열
private ByteBuf[] msgArr;
/*
생성자
SocketAddress, Netty 소켓으로 전송할 ByteBuf 메시지
*/
public NettyClient(SocketAddress addr, ByteBuf[] msgArr) {
this.socketAddress = addr;
this.msgArr = msgArr;
}
/*
생성자
host, 포트, Netty 소켓으로 전송할 ByteBuf 메시지
*/
public NettyClient(String host, int port, ByteBuf[] msgArr) {
this(new InetSocketAddress(host, port), msgArr);
}
//실제로 동작시킬 메소드 Bootstrap 연결 옵션 설정 및 연결 처리
public void run() {
//netty에는 EventLoopGroup이라는 인터페이스가 있으며
//EventGroup은 여러개의 EventLoop를 갖고 있는 풀 방식을 취한다.
//EventLoopGroup에서 새로운 객체를 생성할 때 NioEventLoopGroup 객체를 생성한다.
//이때 저는 최대 쓰레드를 3으로 설정하여 스레드 그룹을 초기화 하였습니다.
bs.group(new NioEventLoopGroup(3))
//채널 초기화
.channel(NioSocketChannel.class)
// 핸들러 등록
.handler(new ChannelInitializer<SocketChannel>() {
//소켓 핸들러에 ChannelInitializer를 등록한다.
// ChannelInitializer 말 그대로 채널 초기함수이다.
@Override
protected void initChannel(SocketChannel ch) throws Exception {
/*
채널 초기화 메소드 initChannel에서 pipeLine에 NettyClientHandler를 등록한다.
이때 파라미터 msgArr은 전송할 메시지의 byteBuf 배열이다.

ChannelPipeline에는 인바운드와 아웃바운드 이벤트에 반응해 작업을 호출하는 풍부한 API가 있다.

채널 파이프라인의 객체 생성
채널 파이프라인에 NettyClientHandler 클래스를 등록하여 클라이언트와 연결이 되었을때
데이터 처리를 담당한다.
*/
ch.pipeline().addLast("clientHandler", new NettyClientHandler(msgArr));
}
})
//소켓 유지 옵션 설정이다..
.option(ChannelOption.SO_KEEPALIVE, true)
;
//실제 네티 소켓 체널 연결
ChannelFuture f = bs.connect(socketAddress);
f.channel();
}

public static void main(String[] args) {

String host = ;
int port = ;

String CLIENT_ID = "발급받은 아이디";
String CLIENT_PASSWORD_LENGTH = "20\0\0";
String CLIENT_PASSWORD = "발급받은 패스워드";
String SESSION_TYPE = "1001";
String REPORT_RECEIVE_YN = "1012";
String YES = "Y";
String PDU_TYPE = "1002";
String PDU_VERSION = "101\0";
String BODY_LENGTH = "49\0\0\0\0\0\0\0\0\0\0";

String body = CLIENT_ID + CLIENT_PASSWORD_LENGTH + CLIENT_PASSWORD + SESSION_TYPE + REPORT_RECEIVE_YN + YES;
String header = PDU_TYPE + PDU_VERSION + BODY_LENGTH;

ByteBuf messageBuffer = Unpooled.buffer();
messageBuffer.writeBytes(header.getBytes());
messageBuffer.writeBytes(body.getBytes());

ByteBuf[] bufArray = new ByteBuf[2];

bufArray[0] = messageBuffer;

String SESSION_CHECK_KEY = "QWER";
String PDU_TYPE1 = "1008";
String BODY_LENGTH2 = "4\0\0\0\0\0\0\0\0\0\0\0";

String body1 = SESSION_CHECK_KEY;
String header1 = PDU_TYPE1 + PDU_VERSION + BODY_LENGTH2;

ByteBuf messageBuffer2 = Unpooled.buffer();
messageBuffer2.writeBytes(header1.getBytes());
messageBuffer2.writeBytes(body1.getBytes());

bufArray[1] = messageBuffer2;


new NettyClient(host, port, bufArray).run();
}
}
1
  • 답변 5

  • 까꿍
    1k
    2022-01-13 10:08:02

    Exception 내용도 알려주세요.

  • Java재밌당
    1k
    2022-01-13 10:11:17 작성 2022-01-13 10:11:54 수정됨


    10:07:41.205 [nioEventLoopGroup-2-1] WARN io.netty.channel.DefaultChannelPipeline - An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
    java.io.IOException: Connection reset by peer
    	at java.base/sun.nio.ch.FileDispatcherImpl.read0(Native Method)
    	at java.base/sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39)
    	at java.base/sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:276)
    	at java.base/sun.nio.ch.IOUtil.read(IOUtil.java:233)
    	at java.base/sun.nio.ch.IOUtil.read(IOUtil.java:223)
    	at java.base/sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:358)
    	at io.netty.buffer.PooledByteBuf.setBytes(PooledByteBuf.java:253)
    	at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1133)
    	at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:350)
    	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:151)
    	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714)
    	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650)
    	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576)
    	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
    	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
    	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    	at java.base/java.lang.Thread.run(Thread.java:834)


  • Java재밌당
    1k
    2022-01-13 10:12:01

    입니다!

  • 준호
    795
    2022-01-13 19:56:30

    로그대로라면 오류가 나서 끊어진 게 아니라 끊어져서 오류가 난겁니다.

  • Java재밌당
    1k
    2022-01-14 08:47:13

    저 Connection reset by peer는 서버측에서 끊어버리는건가요?

  • 로그인을 하시면 답변을 등록할 수 있습니다.