Encoding and decoding technology is simply java serialization technology. There are two purposes of serialization, one is network transmission, the other is object persistence.
We can say that we use java serialization and use netty for transmission, but java serialization has too many disadvantages. For example: java serialization can not cross-language, the stream after serialization is too large, serialization performance is too low, and so on.
Several mainstream codec frameworks:
1.google's Proobuf
Protobuf is an open source project of google, full name of Google Protocol Buffers.
1. Structured Data Storage Format (xml,json, etc.) 2. High Performance Codec Technology 3. Language and platform-independent, scalable 4. Support three languages: java,C++,Python.
2. Thrift of Facebook
Thrift originated from Facebook, which handed Thrift to the apache Foundation as an open source project in 2007. Characteristic:
Thrift supports multiple languages (C++,C#,Cocoa,Erlag,Haskell,java,Ocami,Perl,PHP,Python,Ruby, and SmallTalk) 2.Thrift is suitable for building large-scale data exchange and storage tools. Compared with Json and xml, Thrift has obvious advantages in performance and transmission size for internal data transmission in large-scale systems. 3.Thrift supports three typical coding methods. (Universal Binary Coding, Compression Binary Coding, Optimized Optional Field Compression Coding and Decoding)
3. Introduction to JBoss Marshlling
JBoss Marshalling is a serialization API package for Java objects. It fixes many problems of serialization package that comes with java, but keeps compatible with java.io.Serializable interface. At the same time, it adds some adjustable parameters and additional features. These parameters and features can be configured by factory classes. They are very powerful. Characteristic:
1. Pluggable class parser provides a more convenient strategy for class loading customization, which can be achieved through an interface. 2. Pluggable object replacement technology does not require inheritance. 3. Pluggable predefined class cache tables can reduce the length of serialized byte arrays and improve the serialization performance of commonly used types of objects. 4. No need to implement java.io.Serializable interface 5. Improving the serialization performance of objects by caching technology. 6. It's very simple to use.
Next, netty and marshalling code are serialized
server side
package com.netty.serialize; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; 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; public class Server { public static void main(String[] args) throws Exception{ EventLoopGroup pGroup = new NioEventLoopGroup(); EventLoopGroup cGroup = new NioEventLoopGroup(); ServerBootstrap b = new ServerBootstrap(); b.group(pGroup, cGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 1024) .childHandler(new ChannelInitializer<SocketChannel>() { protected void initChannel(SocketChannel sc) throws Exception { sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder()); sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder()); sc.pipeline().addLast(new ServerHandler()); } }); ChannelFuture cf = b.bind(8888).sync(); cf.channel().closeFuture().sync(); pGroup.shutdownGracefully(); cGroup.shutdownGracefully(); } }
servlerHandler
package com.netty.serialize; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; public class ServerHandler extends ChannelInboundHandlerAdapter{ /** * Channel activation */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("Data activation"); } /** * Channel Data Reading */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { Req req = (Req) msg; System.out.println("The server receives data:"+ req.getId() + ", " + req.getName() + ", " + req.getRequestMessage()); Resp resp = new Resp(); resp.setId(req.getId()); resp.setName("resp" + req.getId()); resp.setResponseMessage("Response content" + req.getId()); ctx.writeAndFlush(resp); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { System.out.println("Data read out"); } }
client side
package com.netty.serialize; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import java.io.File; import java.io.FileInputStream; public class Client { public static void main(String[] args) throws Exception{ EventLoopGroup group = new NioEventLoopGroup(); Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel sc) throws Exception { sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder()); sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder()); sc.pipeline().addLast(new ClientHandler()); } }); ChannelFuture cf = b.connect("127.0.0.1", 8888).sync(); for(int i = 0; i < 5; i++ ){ Req req = new Req(); req.setId("" + i); req.setName("pro" + i); req.setRequestMessage("Data Information" + i); cf.channel().writeAndFlush(req); } cf.channel().closeFuture().sync(); group.shutdownGracefully(); } }
clientHandler
package com.netty.serialize; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.util.ReferenceCountUtil; public class ClientHandler extends ChannelInboundHandlerAdapter { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("Channel activation"); } /** * Channel Data Reading */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { try { Resp resp = (Resp)msg; System.out.println("Client : " + resp.getId() + ", " + resp.getName() + ", " + resp.getResponseMessage()); } finally { ReferenceCountUtil.release(msg); } } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { System.out.println("Receiving return information completed"); } }
MarshallingCodeCFactory
package com.netty.serialize; import io.netty.handler.codec.marshalling.DefaultMarshallerProvider; import io.netty.handler.codec.marshalling.DefaultUnmarshallerProvider; import io.netty.handler.codec.marshalling.MarshallerProvider; import io.netty.handler.codec.marshalling.MarshallingDecoder; import io.netty.handler.codec.marshalling.MarshallingEncoder; import io.netty.handler.codec.marshalling.UnmarshallerProvider; import org.jboss.marshalling.MarshallerFactory; import org.jboss.marshalling.Marshalling; import org.jboss.marshalling.MarshallingConfiguration; /** * Marshalling factory * @author(alienware) */ public final class MarshallingCodeCFactory { /** * Create Jboss Marshalling Decoder * @return MarshallingDecoder */ public static MarshallingDecoder buildMarshallingDecoder() { //Firstly, the serial identifier of Marshalling instance object parameter is obtained through the proficient method of Marshalling tool class, which creates the java sequential chemical plant object. final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial"); //The Marshalling Configuration object is created and the version number is 5. final MarshallingConfiguration configuration = new MarshallingConfiguration(); configuration.setVersion(5); //Create a provider based on marshallerFactory and configuration UnmarshallerProvider provider = new DefaultUnmarshallerProvider(marshallerFactory, configuration); //Construct Netty's MarshallingDecoder object with two parameters: provider and maximum length of a single message serialized MarshallingDecoder decoder = new MarshallingDecoder(provider, 1024 * 1024 * 1); return decoder; } /** * Create Jboss Marshalling Encoder * @return MarshallingEncoder */ public static MarshallingEncoder buildMarshallingEncoder() { final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial"); final MarshallingConfiguration configuration = new MarshallingConfiguration(); configuration.setVersion(5); MarshallerProvider provider = new DefaultMarshallerProvider(marshallerFactory, configuration); //Construct Netty's MarshallingEncoder object, and MarshallingEncoder's POJO object used to implement serialization interface is serialized into binary array. MarshallingEncoder encoder = new MarshallingEncoder(provider); return encoder; } }
Request object
package com.netty.serialize; import java.io.Serializable; public class Req implements Serializable{ private static final long SerialVersionUID = 1L; private String id ; private String name ; private String requestMessage ; private byte[] attachment; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getRequestMessage() { return requestMessage; } public void setRequestMessage(String requestMessage) { this.requestMessage = requestMessage; } public byte[] getAttachment() { return attachment; } public void setAttachment(byte[] attachment) { this.attachment = attachment; } }
Return object
package com.netty.serialize; import java.io.Serializable; public class Resp implements Serializable{ private static final long serialVersionUID = 1L; private String id; private String name; private String responseMessage; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getResponseMessage() { return responseMessage; } public void setResponseMessage(String responseMessage) { this.responseMessage = responseMessage; } }
Test result server
Data activation Server receives data: 0, pro0, data information 0 Server receives data: 1, pro1, data information 1 Server receives data: 2, pro2, data information 2 Server receives data: 3, pro3, data information 3 Server receives data: 4, pro4, data information 4 Data read out
Test results client side
Channel activation Client: 0, resp0, response content 0 Receiving return information completed Client: 1, resp1, response content 1 Client: 2, resp2, response content 2 Client: 3, resp3, response content 3 Client: 4, resp4, response content 4 Receiving return information completed