서버로 전송된 패킷을 디코더로 온전히 복원하고 싶습니다. 잘려서 전송된 패킷 복원 관련

648 views
Skip to first unread message

지헌우

unread,
Mar 27, 2018, 5:59:53 PM3/27/18
to Netty Korean User Group
netty 기반으로 nio tcp 게임서버를 개발하고 있습니다.

클라이언트로부터 전달받는 데이터는 JSON 포멧의 문자열이고 클라이언트로 전달하는 데이터 또한 JSON 포멧의 문자열입니다.

헌데, 전달받는 데이터를 분석한 결과 {"test1":"data1","test2":"data2","test3":"data3"} 라는 포멧을 전달받아야 하는 것이 정상인데

{"test1":"data1","test2":"data2","test3":"data3"}{"test1":"data1","te 와 같이 데이터가 잘려서 전달되는 현상이 발생하고 있고

바로 이어서 전달되는 패킷의 경우 st2":"data2","test3":"data3"} 가 전달되고 있는 상황인데,

현재 이와 같은 패턴으로 전달되는 데이터의 경우 온전한 JSON 포멧만 걸러서 핸들러로 전달하고 있는데

패킷 1

{"test1":"data1","test2":"data2","test3":"data3"}{"test1":"data1","te

패킷 2

st2":"data2","test3":"data3"}

이와 같이 전달된 패킷을

{"test1":"data1","test2":"data2","test3":"data3"}
{"test1":"data1","test2":"data2","test3":"data3"}

로 구분하여 소실되는 input 없이 모두 처리하고 싶은데 잘린 패킷을 어떻게 관리하여야 할지 

도무지 감이 오지 않습니다... 비슷한 문제를 겪어보신 선배님이 계시다면 어떤 방식으로 해결할 수 있는지

조언을 구하고자 합니다.

지헌우

unread,
Mar 27, 2018, 10:49:48 PM3/27/18
to Netty Korean User Group
자체적으로 해결하게 되었습니다.

2018년 3월 28일 수요일 오전 6시 59분 53초 UTC+9, 지헌우 님의 말:

광자검

unread,
Jan 29, 2021, 7:32:11 AM1/29/21
to Netty Korean User Group
안녕하세요 ~

동일한 문제로 해결 방법을 찾다가 ..... 방문하게 되었습니다.

혹시 어떻게 해결 하셨는지 알려주실수 있을까요??



2018년 3월 28일 수요일 오전 11시 49분 48초 UTC+9에 jehw...@gmail.com님이 작성:

ih....@gmail.com

unread,
Feb 2, 2021, 6:51:48 PM2/2/21
to Netty Korean User Group

지헌우

unread,
Feb 2, 2021, 8:36:50 PM2/2/21
to Netty Korean User Group
저는 그때 당시에 MessageToMessageDecoder 를 상속받아서 패컷으로 전달된 데이터(String)를 읽어서 포멧을 검증했었습니다. 
{"test1":"data1","test2":"data2","test3":"data3"}{"test1":"data1","te   이런 식으로 전달된 데이터가 있으면 다음 페킷에서는 
st2":"data2","test3":"data3"} 이런 식의 페킷이 전달되는 것이 확인 되었기 때문에 잘려서 전달된 페킷들을 붙이는 작업을 
따로 코드로 구현했었습니다. 그때 당시에 이런 유형의 버그가 발생했던 원인이 클라이언트 -> 서버로 페킷을 전달할 때,
동시다발적으로 너무 많은 페킷을 전달하니까 서버에서 페킷을 받아들일 때 데이터들이 유실되는 현상들이 있었습니다.
(1:n 의 전투상황에서 n명의 적이 1명을 동시다발적으로 공격할 때, 각각의 적이 공격 이벤트가 수행될 때마다 서버로 페킷을
전송할 때 매우 많은 수의 데이터가 한 번에 서버로 전달되면서 유실이 발생했었음)
그때 당시에 버그가 발생하던 상황이 이러했는데 도움이 되셨으면 합니다. 제가 해결했던 방법은 음... 올바른 해결법이 아니었을 수도 있는데
참고가 되셨으면 합니다. 
2021년 1월 29일 금요일 오후 9시 32분 11초 UTC+9에 kkwa...@gmail.com님이 작성:

광자검

unread,
Feb 2, 2021, 9:16:36 PM2/2/21
to Netty Korean User Group
네~  감사합니다 

ih.... 님  말씀대로 
JsonObjectDecoder을 사용해 봤는데 해결되지 않았습니다. 제가 놓친 부분이 있는 것 같네요 .

우선은 저도 자체적으로 수정했습니다. 
channelReadComplete 올때까지 패킷을 모았다가 channelReadComplete가 오면 json으로 변환해서 넘기는 방식으로 처리했습니다. 
어것 저것 시도하다가 이 방법으로 처리 했는데 , 맞는건지도 잘 모르겠네요 

이렇게 답변 주셔서 정말 감사합니다. 

server init class  

@Override

protected void initChannel(SocketChannel ch) throws Exception {

ChannelPipeline pipeline = ch.pipeline();

pipeline.addLast(new ByteToMessageDecoder() { 

            @Override

           protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {

                          out.add(in.readBytes(in.readableBytes())); 

            }

});

pipeline.addLast(new StringEncoder());

pipeline.addLast(new StringDecoder());

pipeline.addLast(new ServerHandler(sqlSession));

}


ServerHandle class

private String message  = "";

@Override

public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {

try {

JSONObject jsonRequest = new JSONObject(message);

Channel incoming = ctx.channel();

this.process(jsonRequest)

}catch (Exception e){

}finally {
message = "";
ctx.flush();
}
}

@Override

public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

try {
message += (String)msg;
}catch (Exception e){
}
}
 

2021년 2월 3일 수요일 오전 10시 36분 50초 UTC+9에 jehw...@gmail.com님이 작성:

Joo Sing

unread,
Feb 8, 2021, 10:04:25 AM2/8/21
to Netty Korean User Group
안녕하세요. 저는 C,C++ 환경에서 기본 socket으로 네트워크 프로그래밍을 하다가 최근에 JAVA로 프로젝트를 진행하게 되어 Netty를 처음 접한 개발자입니다. 

Netty는 알게된지 3~4일 밖에 되지 않은 초보이지만, TCP 기반 프로그래밍 경험은 조금 있어서 한가지 조언을 드리려구요. 

TCP 프로토콜은 Stream-Oriented 프로그래밍입니다. 이말은 곧 원격지에서 "ABC"를 보내고 "DEF"를 보내면 TCP는 이를 두개의 독립된 메시지 ("ABC", "DEF")로 인식하지 않고, "ABCDEF" 라는 하나의 스트림로 인식한다는 겁니다. 그래서 TCP는 상황에 따라 한번에 "ABCDEF"를 보낼 수도 있고, 때로는 님의 상황처럼 "ABCDE", "F"를 보낼 수도 있다는 뜻입니다. 이건 버그가 아니고, TCP의 특성입니다. TCP 특성에 맞게 메시지 바운더리를 구분해 주는 로직이 사용자 코드에 항상 추가되어야 한다는 뜻입니다. 그러나 Netty는 이런 상황을 대처할 수 있는 Decoder를 제공하는 것 같습니다. (저는 사실 이런 부분을 보고 Netty 프레임워크에 감탄했고, 저희 팀은 Netty를 써야겠다고 확신했습니다) 

Stream-Oriented 한 TCP 프로토콜 특징은 아래 책에서도 잘 설명되어 있구요. 
- Effective TCP/IP Programming / 'Tip 6 TCP가 스트림 프로토콜이라는 것을 기억하라' 

아래 웹페이지의 'Dealing with a Stream-based Transport' 절을 참고하시면 Stream oriented 프로토콜이란 것이 무엇을 의미하는지와 님께서 왜 그런 현상을 접하는지 정확히 설명해 주고 있으니 한 번 읽어보시면 많은 도움이 되설 겁니다. 

그리고 StringDecoder 문서 페이지에도 가보셔도, 아래와 같이 주의사항이 있어요. 
- Please note that this decoder must be used with a proper ByteToMessageDecoder such as DelimiterBasedFrameDecoder or LineBasedFrameDecoder if you are using a stream-based transport such as TCP/IP. A typical setup for a text-based line protocol in a TCP/IP socket would be:

예를 들면 StringDecoder 단 앞에 그냥 ByteToMessageDecoder 를 add해주시는 것이 아니라,  예를들어 메시지 하나하나가 \r\n 개행문자로 끝난다면 LineBasedFrameDecoder 를 pipeline 가장 앞 단에 추가해 주어야 한다는 뜻입니다. LineBasedFrameDecoder 는 아마도 개행문자가 읽어질 때까지는 메시지를 버퍼링해서 구분해서 읽어주는 것으로 보입니다. 아직 코드로 확인해 본적은 저도 없습니다. 

도움이 되셨기를 바랍니다. 

2021년 2월 3일 수요일 오전 11시 16분 36초 UTC+9에 kkwa...@gmail.com님이 작성:

Trustin Lee

unread,
Feb 9, 2021, 1:53:16 AM2/9/21
to Netty Korean Users
자주 질문되는 내용임에도 반복적으로 답하다 보니 이제는 게을러져서 답을 하지 않게 되었는데 자세히 답변해 주셔서 대단히 감사합니다. 부디 본 답변이 검색이 잘 되기를 기대해 봅니다 ㅎㅎ

--
이 메일은 Google 그룹스 'Netty Korean User Group' 그룹에 가입한 분들에게 전송되는 메시지입니다.
이 그룹에서 탈퇴하고 더 이상 이메일을 받지 않으려면 netty-ko+u...@googlegroups.com에 이메일을 보내세요.
웹에서 이 토론을 보려면 https://groups.google.com/d/msgid/netty-ko/2f51ef25-ae97-44c5-9c14-3acb2f6d11c0n%40googlegroups.com을(를) 방문하세요.

Joo Sing

unread,
Feb 9, 2021, 2:06:07 AM2/9/21
to Netty Korean User Group
아 그렇군요. ^^; 

정말 C / C++ 에서 날 코딩으로 통신 프로그램 짜다가 Netty를 몇 일 전에 접하고 정말 Awesome! 을 외쳤는데, 만드신 분과 말을 썪게 되니 신기하기도하고 .. 존경합니다.  

팀 내에 네트워크 통신 모듈 설계에 각자 의견이 많아 논란이 많았는데 Netty를 쓰기로 단결되었습니다. 아직 잘 이해가 안되는 부분이 많은데 종종 질문 남기겠습니다.. ^^; 

감사드립니다. 

2021년 2월 9일 화요일 오후 3시 53분 16초 UTC+9에 이희승 (Trustin Lee)님이 작성:
Reply all
Reply to author
Forward
0 new messages