W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
使用 Netty 時(shí)會(huì)遇到需要解碼以分隔符和長(zhǎng)度為基礎(chǔ)的協(xié)議,本節(jié)講解Netty 如何解碼這些協(xié)議。
經(jīng)常需要處理分隔符協(xié)議或創(chuàng)建基于它們的協(xié)議,例如SMTP、POP3、IMAP、Telnet等等。Netty 附帶的解碼器可以很容易的提取一些序列分隔:
Table 8.5 Decoders for handling delimited and length-based protocols
名稱 | 描述 |
---|---|
DelimiterBasedFrameDecoder | 接收ByteBuf由一個(gè)或多個(gè)分隔符拆分,如NUL或換行符 |
LineBasedFrameDecoder | 接收ByteBuf以分割線結(jié)束,如"\n"和"\r\n" |
下圖顯示了使用"\r\n"分隔符的處理:
Figure 8.5 Handling delimited frames
下面展示了如何用 LineBasedFrameDecoder 處理
Listing 8.8 Handling line-delimited frames
public class LineBasedHandlerInitializer extends ChannelInitializer<Channel> {
@Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new LineBasedFrameDecoder(65 * 1024)); //1
pipeline.addLast(new FrameHandler()); //2
}
public static final class FrameHandler extends SimpleChannelInboundHandler<ByteBuf> {
@Override
public void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { //3
// Do something with the frame
}
}
}
使用 DelimiterBasedFrameDecoder 可以方便處理特定分隔符作為數(shù)據(jù)結(jié)構(gòu)體的這類情況。如下:
清單8.9中顯示了的實(shí)現(xiàn)的方式。定義以下類:
所以關(guān)鍵的解碼器是擴(kuò)展了 LineBasedFrameDecoder
Listing 8.9 Decoder for the command and the handler
public class CmdHandlerInitializer extends ChannelInitializer<Channel> {
@Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new CmdDecoder(65 * 1024));//1
pipeline.addLast(new CmdHandler()); //2
}
public static final class Cmd { //3
private final ByteBuf name;
private final ByteBuf args;
public Cmd(ByteBuf name, ByteBuf args) {
this.name = name;
this.args = args;
}
public ByteBuf name() {
return name;
}
public ByteBuf args() {
return args;
}
}
public static final class CmdDecoder extends LineBasedFrameDecoder {
public CmdDecoder(int maxLength) {
super(maxLength);
}
@Override
protected Object decode(ChannelHandlerContext ctx, ByteBuf buffer) throws Exception {
ByteBuf frame = (ByteBuf) super.decode(ctx, buffer); //4
if (frame == null) {
return null; //5
}
int index = frame.indexOf(frame.readerIndex(), frame.writerIndex(), (byte) ' '); //6
return new Cmd(frame.slice(frame.readerIndex(), index), frame.slice(index +1, frame.writerIndex())); //7
}
}
public static final class CmdHandler extends SimpleChannelInboundHandler<Cmd> {
@Override
public void channelRead0(ChannelHandlerContext ctx, Cmd msg) throws Exception {
// Do something with the command //8
}
}
}
基于長(zhǎng)度的協(xié)議協(xié)議在幀頭文件里定義了一個(gè)幀編碼的長(zhǎng)度,而不是結(jié)束位置用一個(gè)特殊的分隔符來(lái)標(biāo)記。表8.6列出了 Netty 提供的兩個(gè)解碼器,用于處理這種類型的協(xié)議。
Table 8.6 Decoders for length-based protocols
名稱 | 描述 |
---|---|
FixedLengthFrameDecoder | 提取固定長(zhǎng)度 |
LengthFieldBasedFrameDecoder | 讀取頭部長(zhǎng)度并提取幀的長(zhǎng)度 |
如下圖所示,F(xiàn)ixedLengthFrameDecoder 的操作是提取固定長(zhǎng)度每幀8字節(jié)
大部分時(shí)候幀的大小被編碼在頭部,這種情況可以使用LengthFieldBasedFrameDecoder,它會(huì)讀取頭部長(zhǎng)度并提取幀的長(zhǎng)度。下圖顯示了它是如何工作的:
Figure 8.7 Message that has frame size encoded in the header
LengthFieldBasedFrameDecoder 提供了幾個(gè)構(gòu)造函數(shù)覆蓋各種各樣的頭長(zhǎng)字段配置情況。清單8.10顯示了使用三個(gè)參數(shù)的構(gòu)造函數(shù)是maxFrameLength,lengthFieldOffset lengthFieldLength。在這 情況下,幀的長(zhǎng)度被編碼在幀的前8個(gè)字節(jié)。
Listing 8.10 Decoder for the command and the handler
public class LengthBasedInitializer extends ChannelInitializer<Channel> {
@Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(
new LengthFieldBasedFrameDecoder(65 * 1024, 0, 8)); //1
pipeline.addLast(new FrameHandler()); //2
}
public static final class FrameHandler
extends SimpleChannelInboundHandler<ByteBuf> {
@Override
public void channelRead0(ChannelHandlerContext ctx,
ByteBuf msg) throws Exception {
// Do something with the frame //3
}
}
}
總而言之,本部分探討了 Netty 提供的編解碼器支持協(xié)議,包括定義特定的分隔符的字節(jié)流的結(jié)構(gòu)或協(xié)議幀的長(zhǎng)度。這些編解碼器非常有用。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: