Often we are accustomed to calling encoding (Encode) serialization (serialization), which serializes objects into byte arrays for network transmissions, data persistence, or other purposes.
Conversely, decoding (Decode) is called deserialization (deserialization), which restores a byte array read from a network, disk, etc. to the original object (usually a copy of the original object) to facilitate subsequent business logic operations. Java Serialization
The first serialization or codec technology that most Java programmers are exposed to is the Java Default-provided serialization mechanism. The Java object that needs to be serialized can only implement the Java.io.Serializable interface and generate a serialization ID, which is serializable and deserialized through Java.io.ObjectInput and Java.io.ObjectOutput. other serialization Frameworks
The Java default serialization mechanism is inefficient and the serialized code stream is larger, so there are a number of excellent Java serialization frameworks emerging, such as Hessian, PROTOBUF, Thrift, Protostuff, Kryo, Msgpack, Avro, FST Wait a minute. Extended Netty Decoder
Netty provides a io.netty.handler.codec.MessageToByteEncoder and Io.netty.handler.codec.ByteToMessageDecoder interface to facilitate our extended codec.
In order to extend the serialization framework more conveniently, we first define the serializer interface:
Import java.io.IOException;
/**
* @author Ricky Fung * * Public
Interface Serializer {
byte[] encode (Object msg) throws ioexception;< C5/><t> T decode (byte[] buf, class<t> type) throws IOException;
Define Serializer Factory:
Import Com.mindflow.netty4.serialization.hessian.HessianSerializer;
/**
* @author Ricky Fung * * Public
class Serializerfactory {public
static serializer Getserializer () {return
new Hessianserializer ();
}
}
Next, we use the serializer interface defined above in Netty decoder, as follows:
Import Com.mindflow.netty4.serialization.Serializer;
Import Com.mindflow.netty4.serialization.SerializerFactory;
Import Io.netty.buffer.ByteBuf;
Import Io.netty.channel.ChannelHandlerContext;
Import Io.netty.handler.codec.LengthFieldBasedFrameDecoder;
Import Org.slf4j.Logger;
Import Org.slf4j.LoggerFactory;
Import java.io.IOException; /** * ${description} * * @author Ricky Fung/public class Nettymessagedecoder<t> extends
Decoder {private Logger Logger = Loggerfactory.getlogger (GetClass ());
To determine whether the data transmitted by the transmitting client is transmitted according to the Protocol, and the header information should be byte+byte+int = 1+1+4 = 6 private static final int header_size = 6;
Private Serializer Serializer = Serializerfactory.getserializer ();
Private class<t> Clazz;
Public Nettymessagedecoder (class<t> clazz, int maxframelength, int lengthfieldoffset,
int lengthfieldlength) throws IOException {super (maxframelength, Lengthfieldoffset, lengthfieldlength); This.clazz = Clazz;
} @Override protected Object decode (Channelhandlercontext ctx, bytebuf in) throws Exception {
if (In.readablebytes () < header_size) {return null;
} in.markreaderindex ();
Note that during the reading process, the Readindex pointer also moves the byte type = In.readbyte ();
BYTE flag = In.readbyte ();
int datalength = In.readint ();
Logger.info ("Read type:{}, flag:{}, length:{}", type, flag, datalength);
if (In.readablebytes () < datalength) {Logger.error ("body length < {}", datalength);
In.resetreaderindex ();
return null;
} byte[] data = new Byte[datalength];
In.readbytes (data);
try{return Serializer.decode (data, clazz);
catch (Exception e) {throw new RuntimeException ("Serializer decode error"); }
}
}
Nettymessageencoder.java
Import Com.mindflow.netty4.serialization.Serializer;
Import Com.mindflow.netty4.serialization.SerializerFactory;
Import Io.netty.buffer.ByteBuf;
Import Io.netty.channel.ChannelHandlerContext;
Import Io.netty.handler.codec.MessageToByteEncoder;
Import Org.slf4j.Logger;
Import Org.slf4j.LoggerFactory; /** * ${description} * * * @author Ricky Fung/Public final class Nettymessageencoder<t> extends
Tobyteencoder {private Logger Logger = Loggerfactory.getlogger (GetClass ());
Private final byte type = 0X00;
Private final byte flag = 0x0f;
Private Serializer Serializer = Serializerfactory.getserializer ();
Private class<t> Clazz;
Public Nettymessageencoder (class<t> clazz) {this.clazz = Clazz; @Override protected void Encode (Channelhandlercontext ctx, Object msg, bytebuf out) t
Hrows Exception {try {out.writebyte (type);
Out.writebyte (flag); byte[] data = Serializer.encode (msg);
Out.writeint (data.length);
Out.writebytes (data);
Logger.info ("Write type:{}, flag:{}, length:{}", type, flag, data.length);
catch (Exception e) {e.printstacktrace (); }
}
}
Service side:
Import Com.mindflow.netty4.serialization.model.Request;
Import Com.mindflow.netty4.serialization.model.Response;
Import Io.netty.bootstrap.ServerBootstrap;
Import io.netty.channel.*;
Import Io.netty.channel.nio.NioEventLoopGroup;
Import Io.netty.channel.socket.SocketChannel;
Import Io.netty.channel.socket.nio.NioServerSocketChannel;
Import Io.netty.handler.logging.LogLevel;
Import Io.netty.handler.logging.LoggingHandler;
Import Org.slf4j.Logger;
Import Org.slf4j.LoggerFactory;
Import java.io.IOException;
/** * @author Ricky Fung * * public class Nettyserver {private Logger Logger = Loggerfactory.getlogger (GetClass ()); public void bind () throws Exception {//config server-side NIO thread Group Eventloopgroup bossgroup = new Nioeventloopgrou
P (1);
Eventloopgroup Workergroup = new Nioeventloopgroup ();
Serverbootstrap B = new Serverbootstrap (); B.group (Bossgroup, Workergroup). Channel (nioserversocketchannel.class). Option (Channeloption.so_backlog(handler). (New Logginghandler (Loglevel.info)). Childhandler (New Channelinitializer< ;
Socketchannel> () {@Override public void Initchannel (Socketchannel ch) Throws IOException {Ch.pipeline (). AddLast (NE
W nettymessagedecoder<> (Request.class,1<<20, 2, 4));
Ch.pipeline (). AddLast (New Nettymessageencoder (Response.class));
Ch.pipeline (). AddLast (New Nettyserverhandler ());
}
});
Bind port, synchronization waits for success channelfuture future = B.bind (Constants.host, constants.port). sync ();
Logger.info ("Netty Server start OK host:{}, port:{}", Constants.host, Constants.port);
Future.channel (). Closefuture (). sync (); Class Nettyserverhandler extends Simplechannelinboundhandler<request> {@OveRride protected void channelRead0 (Channelhandlercontext context, request request) throws Exception {
Logger.info ("RPC server receive request id:{}", Request.getid ());
Processing request Processrpcrequest (context, request);
@Override public void Exceptioncaught (Channelhandlercontext ctx, Throwable cause) throws Exception {
Logger.error ("Catch exception", cause); } private void Processrpcrequest (final channelhandlercontext context, final request request) {Respons
E response = new response ();
Response.setid (Request.getid ());
Response.setresult ("echo" +request.getmessage ());
Context.writeandflush (response);
public static void Main (string[] args) throws Exception {new Nettyserver (). bind (); }
}
Client:
Import Com.mindflow.netty4.serialization.model.Request;
Import Com.mindflow.netty4.serialization.model.Response;
Import Io.netty.bootstrap.Bootstrap;
Import io.netty.channel.*;
Import Io.netty.channel.nio.NioEventLoopGroup;
Import Io.netty.channel.socket.SocketChannel;
Import Io.netty.channel.socket.nio.NioSocketChannel;
Import Org.slf4j.Logger;
Import Org.slf4j.LoggerFactory;
Import java.net.InetSocketAddress; /** * ${description} * * @author Ricky Fung/public class Nettyclient {private Logger Logger = LOGGERFACTORY.G
Etlogger (GetClass ());
Private Eventloopgroup group = new Nioeventloopgroup (); public void Connect (int port, String host) throws Exception {//Configure client NiO thread group try {Bootstrap
b = new Bootstrap ();
B.group (Group). Channel (niosocketchannel.class). Option (Channeloption.tcp_nodelay, True) . Handler (new channelinitializer<socketchannel> () {@Override
public void Initchannel (Socketchannel ch) throws Exception { Ch.pipeline (). AddLast (New nettymessagedecoder<response>
(Response.class, 1024 * 1024, 2, 4));
Ch.pipeline (). AddLast (New nettymessageencoder<request> (Request.class));
Ch.pipeline (). AddLast (New Nettyclienthandler ());
}
});
Initiates an asynchronous connection operation channelfuture future = B.connect (host, port). sync ();
if (future.awaituninterruptibly (5000)) {Logger.info ("Client Connect host:{}, port:{}", host, Port);
if (Future.channel (). IsActive ()) {Logger.info ("Start sending messages");
for (int i=0; i<100; i++) {Request Req = new request ();
Req.setid ((long) i); Req.setmessage ("Hello World");
Future.channel (). Writeandflush (req);
} logger.info ("Send Message complete"); }} and finally {}} class Nettyclienthandler extends Simplechannelinboundhandler< ; response> {@Override protected void channelRead0 (Channelhandlercontext channelhandlercontext, respons
E msg) throws Exception {final Response Response = msg;
Logger.info ("RPC client receive response id:{}", Response.getid ());
@Override public void Exceptioncaught (Channelhandlercontext ctx, Throwable cause) throws Exception {
Logger.error ("Catch exception", cause); }/** * @param args * @throws Exception/public static void main (string[] args) throws exc
eption {new Nettyclient (). Connect (Constants.port, constants.host); }
}
reference materials
Analysis of Netty Coding and decoding framework of Netty series
Java Depth Adventure (10)--java object serialization and RMI source download
Https://github.com/TiFG/netty4-in-action/tree/master/netty4-serialization-demo