一、編碼器和解碼器
1、什么是編碼和解碼
解碼常用于入站操作,將字節轉換為消息。編碼用于出站,將消息轉換為字節流
2、解碼器ByteToMessageDecoder和ReplayingDecoder,ReplayingDecoder擴展了ByteToMessageDecoder類,使得我們不必使用readableBytes()方法,下面是兩類測試代碼
public class ToIntegerDecoder extends ByteToMessageDecoder {@Overridepublic void decode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List<Object> list) throws Exception {if(in.readableBytes() >=4) {list.add(in.readInt());}}
}
public class ToIntegerDecoder2 extends ReplayingDecoder<Void> {@Overrideprotected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {list.add(byteBuf.readInt());}
}
3、編碼器MessageToByteEncoder和MessageToMessageEncoder,其中T是原始消息的類型,這兩個類分別代表將消息轉換為字節流和將消息轉換為其他類型的消息。下面代碼分別為這兩種的示例代碼
public class ShortToByteEncoder extends MessageToByteEncoder<Short> {@Overrideprotected void encode(ChannelHandlerContext channelHandlerContext, Short aShort, ByteBuf byteBuf) throws Exception {byteBuf.writeShort(aShort);}
}
public class IntegerToStringEncoder extends MessageToMessageEncoder<Integer> {@Overrideprotected void encode(ChannelHandlerContext channelHandlerContext, Integer integer, List<Object> list) throws Exception {list.add(String.valueOf(integer));}
}
4、抽象的編解碼器
ByteToMessageCodec:對編碼和解碼的整合,可以理解為對消息解碼后再次編碼。
MessageToMessageCodec:原理和ByteToMessageCodec同理。
二、內置的編碼器和解碼器
1、通過SSL/TTL保護的netty程序,通常是將SslHandler放在ChannelPipeline的頭部,示例代碼如下:
public class SslChannelInitializer extends ChannelInitializer<Channel> {private final SslContext sslContext;private final boolean startTls;public SslChannelInitializer(SslContext sslContext, boolean startTls) {this.sslContext = sslContext;this.startTls = startTls;//如果設置為true,第一個被寫入的消息將不會被加密}@Overrideprotected void initChannel(Channel channel) throws Exception {SSLEngine sslEngine = sslContext.newEngine(channel.alloc());channel.pipeline().addFirst("ssl", new SslHandler(sslEngine,startTls));}
}
2、構建netty基于http/https協議的:客戶端和服務器分別用HttpClientCodec和HttpServerCodec類即可。
public class HttpInitializer extends ChannelInitializer<Channel> {private final SslContext sslContext;private final boolean isClient;public HttpInitializer(SslContext sslContext, boolean isClient) {this.sslContext = sslContext;this.isClient = isClient;}@Overrideprotected void initChannel(Channel channel) throws Exception {//如果是https協議,則需要在通道下的管道頭部追加SslHandlerChannelPipeline pipeline = channel.pipeline();SSLEngine engine = sslContext.newEngine(channel.alloc());pipeline.addFirst("ssl", new SslHandler(engine));if(isClient){pipeline.addLast("codec", new HttpClientCodec());}else {pipeline.addLast("codec", new HttpServerCodec());}}
}
3、websocket:websocket的WebSocketFrame類型通常包括BinaryWebSocketFrame(數據幀,二進制數據)、TextWebSocketFrame(數據幀,文本數據)、CloseWebSocketFrame(控制幀,一個Close請求、關閉的狀態碼及關閉的原因)、PingWebSocketFrame(控制幀,請求一個PongWebSocketFrame)和PongWebSocketFrame(控制幀,對PingWebSocketFrame進行響應)。
示例代碼
websocket的處理類
public class TextFrameHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {@Overridepublic void messageReceived(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception {}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception{//處理數據}
}
public class WebsocketServerInitializer extends ChannelInitializer<Channel> {@Overridepublic void initChannel(Channel ch) throws Exception {ch.pipeline().addLast(new HttpServerCodec(),new HttpObjectAggregator(65536),new WebSocketServerProtocolHandler("/websocket"),new TextFrameHandler());}
}
4、空閑的連接和超時
IdleStateHandler:當連接空閑時間太長會觸發事件。ReadTimeoutHandler讀超時處理器,WriteTimeoutHandler寫超時處理器
用法也是將他們的對象注冊到通道里的管道中去。
channel.pipeline().addLast(new IdleStateHandler(0, 0, 60, TimeUnit.SECONDS));