Introduction
String is the most commonly used message format in our program, and it is also the simplest message format, but because the string is too simple to add more information, we choose to use byteBuf as the bottom layer in netty. Messaging carrier.
Although ByteBuf is used at the bottom, for programmers, they still want to be able to use this simplest string format, so is there any easy way?
String codec in netty
In order to solve the problem of passing strings in netty's channel, netty provides encoding and decoding for strings, namely StringEncoder and StringDecoder.
Let's see how they are used in the program, the first is to add StringDecoder and StringEncoder to channelPipeline:
ChannelPipeline pipeline = ...;
// Decoders
pipeline.addLast("frameDecoder", new LineBasedFrameDecoder(80));
pipeline.addLast("stringDecoder", new StringDecoder(CharsetUtil.UTF_8));
// Encoder
pipeline.addLast("stringEncoder", new StringEncoder(CharsetUtil.UTF_8));
Note that here we also call LineBasedFrameDecoder before using StringDecoder, first divide the data by line, and then read the string.
So someone wants to ask, the decoder has added LineBasedFrameDecoder preprocessing, why is there no line separator added when writing?
In fact, there are two ways to deal with it. The first is to manually add line separators when writing strings to the channel, as shown below:
void channelRead(ChannelHandlerContext ctx, String msg) {
ch.write("Did you say '" + msg + "'?\n");
}
If you don't want to add a newline after msg every time, you can replace StringEncoder with LineEncoder, and the above pipeline becomes as follows:
ChannelPipeline pipeline = ...;
// Decoders
pipeline.addLast("frameDecoder", new LineBasedFrameDecoder(80));
pipeline.addLast("stringDecoder", new StringDecoder(CharsetUtil.UTF_8));
// Encoder
pipeline.addLast("lineEncoder", new LineEncoder(LineSeparator.UNIX, CharsetUtil.UTF_8));
This way, we don't need to manually add newlines in the handler, like this:
void channelRead(ChannelHandlerContext ctx, String msg) {
ch.write("Did you say '" + msg + "'?");
}
Line breaks for different platforms
Friends who have passed text files on unix and windows platforms may encounter a problem, that is, the text files created by windows, if they are opened under unix, you will find that there is an extra special character after each line, this is because unix and windows Platform-defined line breaks are different.
On the unix platform, "\n" is usually used to wrap the line, while on the windows platform, ""\r\n" is used to wrap the line.
Because the java program is cross-platform, the written program may run on the unix platform or the windows platform, so we need a way to get the newline character of the platform, netty provides a class of LineSeparator to complete this work.
There are three definitions of newlines in LineSeparator, namely:
public static final LineSeparator DEFAULT = new LineSeparator(StringUtil.NEWLINE);
public static final LineSeparator UNIX = new LineSeparator("\n");
public static final LineSeparator WINDOWS = new LineSeparator("\r\n");
UNIX and WINDOWS are well understood, they are the different platforms we just talked about.
So what is DEFAULT? The NEWLINE passed in DEFAULT is actually obtained from the system properties. If it is not obtained, the default "\n" is used.
public static final String NEWLINE = SystemPropertyUtil.get("line.separator", "\n");
Implementation of String Encoding
We mentioned above that the classes related to string encoding and decoding are StringEncoder, LineEncoder and StringDecoder. Let's look at the implementation of these three classes in detail.
The first is StringEncoder, StringEncoder inherits MessageToMessageEncoder:
public class StringEncoder extends MessageToMessageEncoder<CharSequence>
CharSequence in generics means that the object to be encoded by StringEncoder is CharSequence, which is a sequence of characters.
Although everyone commonly uses the String class, not everyone knows that String is actually a subclass of CharSequence, so StringEncoder can also encode strings.
The encoding logic of StringEncoder is very simple. Convert the incoming string msg into CharBuffer, and then call the encodeString method of ByteBufUtil to convert it into ByteBuf and add it to out:
protected void encode(ChannelHandlerContext ctx, CharSequence msg, List<Object> out) throws Exception {
if (msg.length() == 0) {
return;
}
out.add(ByteBufUtil.encodeString(ctx.alloc(), CharBuffer.wrap(msg), charset));
}
LineEncoder is very similar to StringEncoder, it also inherits from MessageToMessageEncoder:
public class LineEncoder extends MessageToMessageEncoder<CharSequence>
The difference is the encoder method:
protected void encode(ChannelHandlerContext ctx, CharSequence msg, List<Object> out) throws Exception {
ByteBuf buffer = ByteBufUtil.encodeString(ctx.alloc(), CharBuffer.wrap(msg), charset, lineSeparator.length);
buffer.writeBytes(lineSeparator);
out.add(buffer);
}
The encodeString of ByteBufUtil has an additional lineSeparator.length parameter, which is used to reserve the position of lineSeparator, and then adds lineSeparator to the returned ByteBuf as the final output.
StringDecoder is the inverse of StringEncoder:
public class StringDecoder extends MessageToMessageDecoder<ByteBuf>
The ByteBuf here means that the object to be decoded is ByteBuf. Let's take a look at his decoding method:
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
out.add(msg.toString(charset));
}
The ByteBuf can be converted to a string by directly calling the msg.toString method.
Summarize
The above is the codec for strings in netty. By using these codecs, our work can be greatly simplified.
This article has been included in http://www.flydean.com/14-6-netty-codec-string/
The most popular interpretation, the most profound dry goods, the most concise tutorials, and many tricks you don't know are waiting for you to discover!
Welcome to pay attention to my official account: "Program those things", understand technology, understand you better!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。