본문 바로가기

IT for developer/Netty

Netty 예제 분석 - Telnet

Telnet

http://docs.jboss.org/netty/3.2/xref/org/jboss/netty/example/telnet/package-summary.html

 
우선 클라이언트를 살펴보자.
main 함수에서 키보드로 입력한 데이터를 서버에 전송한다. 직접 서버에 데이터를 전송한다. 'bye' 를 칠때 까지 계속 전송한다. 'bye'를 치면 접속을 종료한다.


71          // Read commands from the stdin.
72 ChannelFuture lastWriteFuture = null;
73 BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
74 for (;;) {
75 String line = in.readLine();
76 if (line == null) {
77 break;
78 }
79
80 // Sends the received line to the server.
81 lastWriteFuture = channel.write(line + "\r\n");
82
83 // If user typed the 'bye' command, wait until the server closes
84 // the connection.
85 if (line.toLowerCase().equals("bye")) {
86 channel.getCloseFuture().awaitUninterruptibly();
87 break;
88 }
89 }


TelnetClientPipelineFactory를 파이프라인 팩토리로 지정하고 있다.
58          bootstrap.setPipelineFactory(new TelnetClientPipelineFactory());

Telnet ClientPipelineFactory는 4가지 핸들러를 등록하고있다.

44          pipeline.addLast("framer", new DelimiterBasedFrameDecoder(
45 8192, Delimiters.lineDelimiter()));
46 pipeline.addLast("decoder", new StringDecoder());
47 pipeline.addLast("encoder", new StringEncoder());
48
49 // and then business logic.
50 pipeline.addLast("handler", new TelnetClientHandler());

DelimeterBasedFrameDecoder: 업스트림
StringDecoder: 업스트림
StringEncoder: 다운스트림
TelentClientHandler: 업스트림

데이터를 수신할 때 다음과 같은 순서로 이벤트를 처리한다.
DelimeterBasedFrameDecoder --> StringDecoder --> TelnetClientHandler

DelimeterBasedFrameDecoder :받은 데이터를 하나이상의 구분자로 짤라주는 디코더이다. 이 예제에서는 lineDelimeter 로 구분해서 짤라주는 역할을 한다.

StringDecoder :ChannelBuffer를 문자열로 변환해준다.

TelnetClientHandler은 서버로 부터 받은 데이터를 화면에 출력한다.

50      @Override
51      public void messageReceived(
52              ChannelHandlerContext ctx, MessageEvent e) {
53          // Print out the line received from the server.
54          System.err.println(e.getMessage());
55      }


자 이제 서버를 살펴보자. 분명 클라이언트측 핸들러들과 대응되는 핸들러들을 가지고 있을듯.

TelnetServierPipelineFactory를 보면 다음과 같다.

44          pipeline.addLast("framer", new DelimiterBasedFrameDecoder(
45                  8192, Delimiters.lineDelimiter()));
46          pipeline.addLast("decoder", new StringDecoder());
47          pipeline.addLast("encoder", new StringEncoder());
48  
49          // and then business logic.
50          pipeline.addLast("handler", new TelnetServerHandler());


클라이언트로 부터 데이터를 수신할 때 클라이언트와 유사하게 DelimeterBasedFrameDecoder --> StringDecoder --> TelnetServerHandler 순으로 이벤트가 처리한다.

여기서는 TelnetClientHandler대신 사용된 TelnetServerHandler 를 살펴보면 되겠다.
그냥  요청받은 명령을 클라이언트에게 돌려주거나 bye 명령을 받은 경우 연결을 끊어준다. 

64 public void messageReceived(
65              ChannelHandlerContext ctx, MessageEvent e) {
66  
67          // Cast to a String first.
68          // We know it is a String because we put some codec in TelnetPipelineFactory.
69          String request = (String) e.getMessage();
70  
71          // Generate and write a response.
72          String response;
73          boolean close = false;
74          if (request.length() == 0) {
75              response = "Please type something.\r\n";
76          } else if (request.toLowerCase().equals("bye")) {
77              response = "Have a good day!\r\n";
78              close = true;
79          } else {
80              response = "Did you say '" + request + "'?\r\n";
81          }
82  
83          // We do not need to write a ChannelBuffer here.
84          // We know the encoder inserted at TelnetPipelineFactory will do the conversion.
85          ChannelFuture future = e.getChannel().write(response);
86  
87          // Close the connection after sending 'Have a good day!'
88          // if the client has sent 'bye'.
89          if (close) {
90              future.addListener(ChannelFutureListener.CLOSE);
91          }
92