Make writing a habit together! This is the 14th day of my participation in the “Gold Digging Day New Plan · April More Text Challenge”. Click here for more details.
Introduction to the
String is the most commonly used message format in our program, and it is also the simplest message format, but because string is too simple to attach any more information, we chose to use byteBuf as the lowest level messaging carrier in Netty.
Although the underlying ByteBuf is used, programmers still want to be able to use the simplest string format, so is there an easy way?
A string codec in Netty
To solve the problem of passing strings through Netty’s channels, Netty provides StringEncoder and StringDecoder for strings.
Let’s take a look at how they are used in the program, first adding StringDecoder and StringEncoder to the 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));Copy the code
Note that here we also call LineBasedFrameDecoder before using StringDecoder, which splits the data into rows and then reads the string.
LineBasedFrameDecoder has been preprocessed by LineBasedFrameDecoder. Why not add a line separator to the framedecoder?
There are actually two ways to do this. The first is to write a string to a channel by manually adding a line separator, as shown below:
void channelRead(ChannelHandlerContext ctx, String msg) { ch.write("Did you say '" + msg + "'? \n"); }Copy the code
If you don’t want to add a newline to MSG every time, you can replace StringEncoder with LineEncoder, and the pipeline above looks like this:
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));Copy the code
This way, we don’t need to manually add newlines to the handler, as shown below:
void channelRead(ChannelHandlerContext ctx, String msg) { ch.write("Did you say '" + msg + "'?" ); }Copy the code
Newline characters for different platforms
Those of you who have passed text files on Unix and Windows platforms may run into a problem. Windows created text files that, if opened under Unix, have a special character at the end of each line. This is because Unix and Windows platforms define line breaks differently.
On Unix platforms, “\n” is usually used to wrap a line, while on Windows, “”\r\n” is used to wrap a line.
Java programs can run on Unix platforms or Windows platforms, so we need a way to get platform newlines. Netty provides a LineSeparator class to do this.
LineSeparator has three definitions of line breaks:
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");
Copy the code
UNIX and WINDOWS are easy to understand, they are the different platforms we just talked about.
So what is DEFAULT? The NEWLINE passed in DEFAULT is actually retrieved from the system property. If not, the DEFAULT “\n” is used.
public static final String NEWLINE = SystemPropertyUtil.get("line.separator", "\n");
Copy the code
The implementation of string encoding
The classes that encode and decode strings are StringEncoder, LineEncoder, and StringDecoder. Let’s look at the implementation of these three classes in detail.
StringEncoder, StringEncoder inherits MessageToMessageEncoder:
public class StringEncoder extends MessageToMessageEncoder<CharSequence>
Copy the code
The CharSequence in the generic stands for StringEncoder and the object to encode is a CharSequence, which is a sequence of characters.
Although String is a common class, you may not know that String is a subclass of CharSequence, so StringEncoder can encode strings as well.
StringEncoder’s encoding logic is very simple. Convert the string MSG into CharBuffer, and then call ByteBufUtil’s encodeString method 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));
}
Copy the code
LineEncoder is similar to StringEncoder in that it also inherits from MessageToMessageEncoder:
public class LineEncoder extends MessageToMessageEncoder<CharSequence>
Copy the code
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);
}
Copy the code
The encodeString of ByteBufUtil has an extra parameter, lineseparator. length, which is used to reserve the location of the lineSeparator, and then adds lineSeparator to the end of the returned ByteBuf as output.
StringDecoder is the opposite of StringEncoder:
public class StringDecoder extends MessageToMessageDecoder<ByteBuf>
Copy the code
The object to decode is ByteBuf. Let’s look at its decoding method:
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
out.add(msg.toString(charset));
}
Copy the code
To convert ByteBuf to a string, call msg.toString directly.
conclusion
These are the codecs for strings in Netty. Using these codecs can greatly simplify our work.
This article is available at www.flydean.com/14-6-netty-…
The most popular interpretation, the most profound dry goods, the most concise tutorial, many tips you didn’t know waiting for you to discover!
Welcome to pay attention to my public number: “procedures those things”, understand technology, more understand you!