길이를 예측할 수 없는 메시지(전문)를 수신하는 경우 ByteBuf사이즈 이상 한번에 수신하는 방법?

6,436 views
Skip to first unread message

Myungkyu Jung

unread,
Jul 20, 2015, 11:44:36 PM7/20/15
to nett...@googlegroups.com
안녕하세요 Netty 초보자입니다.^^;
훌륭한 Netty를 이용해 서버 데몬 만들어 보다 질문이 있어 이렇게 문의 드립니다.


> Netty Version: netty-all-4.0.9.Fianl.jar

> 목적: 전문길이가 1024보다 큰 소켓서버 데몬 개발 시 수신전문, 송신전문을 (ByteBuf의 길이만큼이 아닌) 한번에 수신/송신을 하고 싶음.

> 질문: 전문길이를 미리 예측할 수 없을 때 소켓으로부터 데이터를 한번에 받고 보낼 수 있는 방법이 있나요?
즉,
전문길이를 미리 예측할수 없을때
전문 이 다 수신된다음에 Handler에게 channelRead()이벤트를 주고 싶습니다.



여기 올라온 글이나 Netty UserGuide를 보면
ByteToMessageDecoder 를 상속받아 decoder()를 override하면 된다고 알고 있습니다.

몇 byte가 들어올지 알고 있으면 그때까지 대기하다가 다 들어오면
out.add(in.readBytes());
하게 되어있는것 같더라구요.
(제가 이해한게 맞는지 모르겠지만;;;ㅎㅎ)


하지만

제가 하고싶은것은 몇 byte가 들어올지 모르는 상태에서
그저 socket 에서 더이상 읽을 데이터가 없을때까지 다 모아서 한번에 channelRead()에 던지고 싶습니다.

또한 클라이언트에게 1024byte이상 write를 할때도 
두번에 나눠서 전송하지 말고 한번에 클라이언트에게 전송하고 싶습니다.

위 두가지 를 할 수 있는 방법이 있는 지 고수님들 한 가르침 부탁드립니다.



p.s)
setRecvByteBufAllocator(new FixedRecvByteBufAllocator())를 이용하는건
다른곳에 이희승님께서 메모리 남용이 많을것 같다고 말씀하신걸 보고 저도 피하고싶습니다.^^;


이희승 (Trustin Lee)

unread,
Jul 21, 2015, 9:06:43 AM7/21/15
to nett...@googlegroups.com
'socket 에서 더이상 읽을 데이터가 없을때까지' 
 
일반적으로 보았을 때 확실히 그렇게 말할 수 있는 때는 커넥션이 닫혔을 때 뿐입니다.
 
메시지의 길이 필드가 명시적으로 존재하지 않는 프로토콜에도 맥락에 따라 메시지의 길이가 결정되므로 길이를 알 수 있는 시점에 차이가 있을 뿐 알 수 없는 것은 아닙니다.  예를 들어 대역폭 사용량을 줄일 목적으로 컴팩트하게 설계된 SOCKS같은 프로토콜에는 길이 필드가 없습니다. 하지만 해석하다보면 어디에서부터 새 메시지가 시작되는지 충분히 알 수 있습니다.
 
여튼 구현하고자 하는 프로토콜에 대한 자세한 정보를 주시면 좀 더 유용한 답변을 드릴 수 있을 것 같습니다.
 
--
--
이 메일은 Google 그룹스 'Netty Korean User Group' 그룹에 가입한 분들에게 전송되는 메시지입니다.
이 그룹에서 탈퇴하고 더 이상 이메일을 받지 않으려면 netty-ko+u...@googlegroups.com에 이메일을 보내세요.
더 많은 옵션을 보려면 https://groups.google.com/d/optout을(를) 방문하세요.
 

Myungkyu Jung

unread,
Jul 21, 2015, 8:47:26 PM7/21/15
to Netty Korean User Group
답변 감사합니다. (^^)(__)

구현하고자 하는 설명이 부족했나 보네요 ;;;ㅎㅎ

자세히 다시 설명드리겠습니다. 

ByteBuf의 사이즈가 1024이고
A전문이 어떨때는 100bytes, 어떨때는 2,000bytes 와 같이 가변적일때
channelRead()에서 받는 Object msg 에 2,000bytes 모두 한번에 받을 수 있는 방법을 알고 싶습니다.
(socket통신)

전문의 길이를 미리 알수 만 있으면 decode()에서 그 길이만큼 올때까지 대기하다 리턴하면 되는데
미리 알수 있는 방법이 없어 (전문 내 메시지 길이 정보 없다는 가정하에) 어떻게 구현해야할 지 궁금합니다.




2015년 7월 21일 화요일 오후 10시 6분 43초 UTC+9, 이희승 (Trustin Lee) 님의 말:

이희승 (Trustin Lee)

unread,
Jul 21, 2015, 9:14:25 PM7/21/15
to nett...@googlegroups.com
어떨 때 100 바이트 어떨 때 2000 바이트이면 예를 들어 상대방이 100바이트 메시지 하나 2000바이트 메시지 하나를 보냈을 때 한 번에 2100 바이트가 읽힐 수 있을텐데요.  그 경우에는 어떻게 구분하게 되나요?

Myungkyu Jung

unread,
Jul 21, 2015, 10:33:07 PM7/21/15
to Netty Korean User Group
아, 클라이언트는 데이터를 나눠서 보내지 않고 무조건 한번에 보낸다는 가정이 빠졌군요; 죄송합니다.

case1:
클라이언트 connect to 서버
클라이언트 -> 메시지1,500byte -> 서버
클라이언트 <- 메시지 2,000byte <- 서버
close connect

case2:
클라이언트 connect to 서버
클라이언트 -> 메시지 600byte -> 서버
클라이언트 <- 메시지 3,000byte <- 서버
close connect


case 1,2모두 전혀 다른 connect입니다. 클라이언트와 서버는 모두 나눠서 전송하지는 않고 무조건 한번에 전송합니다.
데이터 길이는 항상 가변이니 저건 예일 뿐입니다.



2015년 7월 22일 수요일 오전 10시 14분 25초 UTC+9, 이희승 (Trustin Lee) 님의 말:

kris jeong

unread,
Jul 22, 2015, 2:46:30 PM7/22/15
to nett...@googlegroups.com
희승님이 말씀하신 내용은 TCP/IP 스펙상 클라이언트의 전송단위와 서버의 수신단위가 일치하지 않는 문제를 해결하기 위해서 어떻게 처리하시는지 질문한걸로 보입니다.

TCP/IP의 데이터를 전송은 나누어서 write/flush 하더라도 실제 전송은 한꺼번에 될 수도 있습니다.
이 부분은 운영체제의 TCP전송 버퍼, 네이글 알고리즘, 실제 네트워크의 상황등에 따라서 달라집니다.
즉, 애플리케이션의 전송단위(write/flush)와 TCP/IP 레이어에서 데이터 흐름은 항상 일치하지 않습니다.

결국 TCP/IP 레이어에서 데이터 송수신을 위해서는 보통 아래와 같이 3가지 방법중에 하나를 선택합니다.

1. 데이터 송수신을 명확하게 하기 위해서 패킷의 길이를  데이터에 명시하는 방법.
      ex) 데이터의 첫 몇 바이트를 사용하여 전송할 데이터의 길이를 명시.
2. 데이터의 종료를 알리는 구분자를 데이터에 포함하는 방법.
      ex) telnet 서버와 같이 CRLF가 도달 할 때까지 수신.
3. 송수신 데이터의 길이를 미리 지정하는 방법. 
      ex) 송수신할 데이터의 크기는 항상 1024 바이트.

위와 같은 처리를 네티에서 구현하는 방법은 아래 링크의 문서를 참고하시면 될 것 같습니다.





2015년 7월 22일 오전 11:33, Myungkyu Jung <taeb...@gmail.com>님이 작성:
--
이 메일은 Google 그룹스 'Netty Korean User Group' 그룹에 가입한 분들에게 전송되는 메시지입니다.
이 그룹에서 탈퇴하고 더 이상 이메일을 받지 않으려면 netty-ko+u...@googlegroups.com에 이메일을 보내세요.

Myungkyu Jung

unread,
Jul 28, 2015, 1:00:28 AM7/28/15
to Netty Korean User Group, smu...@gmail.com
답변 주셔서 감사합니다.

그냥 간단히 예를 들어 질문을 드리는게 낫겠네요 ^^;

github에 이희승님께서 올려놓으신 sample중에 proxy 소스가 있습니다.

그 소스를 사용하는 경우  ByteBuf사이즈가 1024보다 큰 1500 bytes 인 경우 1024,476 이렇게 두번에 
걸쳐서 read되고 write도 두번에 나누어서 됩니다.
(클라이언트,서버가 모두 1500bytes를 한번에 보내고 네트워크상에서나 OS설정과 무관한 경우에도)

이 때 전문길이를 미리 알수 없을때 두번이 아닌 한번에 read/write하는 방법을 알고 싶습니다.

- 전문길이를 알거나 전문종료flag를 알고 decode하는 방법은 다양한 전문형식에서 범용적으로 사용하고자 하니 미리 알기가 어렵습니다.
- ByteBuf사이즈 미리 늘리는 방법도 이미 알고 있지만 비효율적이라 다른방법이 있는지 궁금합니다.


정말로 방법이 위의 두가지 밖에 없다고 한다면 조용히 희망을 접고 ByteBuf를 늘려야 겠네요 ㅠ.ㅠ


Reply all
Reply to author
Forward
Message has been deleted
Message has been deleted
0 new messages