2014-04-15 2 views
1

netty를 기반으로 REST 서버를 작성했습니다. 4. 클라이언트 처리기는 다음과 유사합니다.소켓 메시지가 netty로 분할 됨

netty가 제공하는 msg의 바이트 버퍼 용량은 다양합니다. 클라이언트 메시지가 버퍼보다 ​​클 경우 메시지는 분할됩니다. 내가 찾은 것은 각 조각에 대해 channelRead와 ChannelReadComplete가 모두 호출된다는 것입니다. 내가 보통 보는 것은 ByteBuf가 약 512이고 메시지가 600 주위에 있다는 것입니다. 첫 번째 512 바이트는 channelReadComplete, 그 다음 나머지 100 바이트는 channelReadComplete, channelReadComplete는 channelReadComplete가 있습니다. 2 대신에 2 개의 메시지.

여기 몇 가지 관련 질문을 발견했지만 channelReadComplete의 요점은 무엇입니까? 모든 채널을 읽은 후에 실제로 호출됩니까? 사용 가능한 바이트가있는 한, channelReadComplete가 호출되기 전에 이들을 읽지 않아야합니까?

public class ClientHandler extends ChannelInboundHandlerAdapter { 
    .... 
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 
     Report.debug("Read from client"); 
     ByteBuf buf = (ByteBuf) msg; 
     String contents = buf.toString(io.netty.util.CharsetUtil.US_ASCII); 
     ReferenceCountUtil.release(msg); 

     ClientConnection client = ClientConnection.get(ctx); 
     if (client != null) { 
      client.messageText(contents); // adds text to buffer 
      return; 
     } 
     ((parse serial number from contents, process registration)) 
     ClientConnection.online(serialNumber, ctx);  // register success, create the client object 
    } 

    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { 
     ClientConnection client = ClientConnection.get(ctx); 
     if (client == null) 
      Report.debug("completed read of message from unregistered client"); 
     else { 
      Report.debug("completed read of message from client " + client.serialNumber()); 
      String contents = client.messageText(); 
      ... ((process message)) 
     } 
    } 
} 

답변

0

예, channelReadComplete()는 파이프 라인의 각 channelRead()가 완료된 후에 호출됩니다. channelRead()에서 예외가 발생하면 ecxeptionCaught() 메서드로 점프합니다.

성공적인 channelRead()에서만 실행하려는 코드를 channelReadComplete()에 넣어야합니다.

예를 들어이 우리의 프로젝트가하는 일입니다 : 클라이언트가 "OK"그는 나머지를 보낼 수없는 다른 무언가를 수신

@Override 
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 
    // compute msg 
    ctx.fireChannelRead(msg); //tells the next handler 
           //in pipeline (if existing) to read the channel 
} 

@Override 
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { 
    ctx.writeAndFlush("OK"); 
    ctx.fireChannelReadComplete(); 
} 

@Override 
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 
    logger.error(Message.RCV_ERROR, cause.getMessage()); 
    ctx.writeAndFlush(cause.getMessage()); 
    ctx.close(); 
} 

합니다. 모든 패키지가 다음 도착 후 호출되는 방법을 찾고 있다면 :

@Override 
public void channelInactive(ChannelHandlerContext ctx) throws Exception { 
    //close the writer that wrote the message to file (for example) 
} 

편집 : 당신은 또한 더 큰 패키지를 전송 시도 할 수 있습니다. 메시지 크기는 클라이언트가 제어한다고 생각합니다.

1

각 채널 읽기 후에 channelReadComplete가 호출되지 않습니다. netty 이벤트 루프는 더 이상 읽을 데이터가 없거나 포기해야 할 때까지 NIO 소켓에서 읽고 여러 채널 읽기를 시작합니다. 그러면 channelReadComplete가 시작됩니다.