Author: rickiyang
source: www.cnblogs.com/rickiyang/p/11074232.html
Let's use Protobuf for serialization. Like xml and json, it has its own syntax. The suffix of xml is The suffix of xml and json files is json, naturally, the suffix of Protobuf file is proto (haha, of course not the full name).
Let's use Protobuf to encapsulate a message and briefly introduce its use through a case.
First, we use the syntax format of Protobuf to write an object that needs to be serialized. The naming format is MSG proto
option java_package = "cn.edu.hust.netty.demo10"; option java_outer_classname = "MessageProto"; message RequestMsg{ required bytes msgType = 1; required string receiveOne = 2; required string msg = 3; } message ResponseMsg{ required bytes msgType = 1; required string receiveOne = 2; required string msg = 3; }
About message For details of the syntax format in proto, please google the relevant instructions. There are many introductions on the Internet. Again, briefly explain the above syntax:
- option java_package: indicates the generated Package name of java file
- option java_outer_classname: the file name of the generated java file
- message: is its basic type, just like class in java
Field modifier:
- required: a well formed message must contain one such field. Indicates that the value must be set;
- optional: the field in the message format can have 0 or 1 values (no more than 1).
- Repeated: in a well formed message, this field can be repeated any number of times (including 0 times). The order of duplicate values is preserved. Indicates that the value can be repeated, which is equivalent to List in java.
The character types are slightly different: double,float,int32,int64,bool(boolean),string,bytes. Slightly different. String, boolean and int are different.
In addition, we can see that the above three fields are assigned values respectively. What does this value mean? In the message definition, each field has a unique numeric identifier. These identifiers are used to identify each field in the binary format of the message and cannot be changed once they are used. Note: the identification number within [1,15] will occupy one byte during encoding. The identification number within [162047] takes up 2 bytes. Therefore, the identification number within [1,15] should be reserved for those frequently occurring message elements.
Let's briefly introduce the syntax of Protobuf. For more details, please refer to the document yourself. Let's start serializing using Protobuf.
First, we introduce the jar package of protobuf into the project. At present, the official version is up to 3.2. Let's use 3.0:
<dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>3.0.2</version> </dependency>
The Protobuf file has been defined, so we need to compile it into java code. Here, we use the script tool protoc provided by google. The link is here. Click download. The provided here is protoc-3.0.2. Note that the version of protocol needs to correspond to the version of Protobuf, otherwise there will be some differences between different versions, and there may be problems in parsing. Now we know why we have to choose Protobuf3 Version 0.2, because I didn't find another version of protocol...
After downloading, we unzip the MSG we just wrote Copy the proto file.
Then we enter cmd and enter the following command:
Mainly the third command. If there is no error in your input, your proto folder should generate a subfolder:
Go into this folder and you will see that messageproto has been generated Java file, congratulations. At this time, you have completed the generation of protobuf serialization file. Then you copy the file to the project directory.
Next, let's use the generated file to send messages. Or the old routine of server and client.
Server:
public class ProtoBufServer { private int port; public ProtoBufServer(int port) { this.port = port; } public void start(){ EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workGroup = new NioEventLoopGroup(); ServerBootstrap server = new ServerBootstrap().group(bossGroup,workGroup) .channel(NioServerSocketChannel.class) .childHandler(new ServerChannelInitializer()); try { ChannelFuture future = server.bind(port).sync(); future.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); }finally { bossGroup.shutdownGracefully(); workGroup.shutdownGracefully(); } } public static void main(String[] args) { ProtoBufServer server = new ProtoBufServer(7788); server.start(); } }
Server Initializer:
public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { ChannelPipeline pipeline = socketChannel.pipeline(); pipeline.addLast(new ProtobufVarint32FrameDecoder()); pipeline.addLast(new ProtobufDecoder(MessageProto.RequestMsg.getDefaultInstance())); pipeline.addLast(new ProtoBufServerHandler()); } }
Server handler:
public class ProtoBufServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { MessageProto.ResponseMsg.Builder builder = MessageProto.ResponseMsg.newBuilder(); builder.setMsgType(ByteString.copyFromUtf8("CBSP")); builder.setReceiveOne("Xiao Hong"); builder.setMsg("Hello, what can I do for you"); ctx.writeAndFlush(builder.build()); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { MessageProto.RequestMsg m = (MessageProto.RequestMsg)msg; System.out.println("Client say: "+m.getReceiveOne()+","+m.getMsg()); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { super.exceptionCaught(ctx, cause); ctx.close(); } }
client:
public class ProtoBufClient { private int port; private String address; public ProtoBufClient(int port, String address) { this.port = port; this.address = address; } public void start(){ EventLoopGroup group = new NioEventLoopGroup(); Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group) .channel(NioSocketChannel.class) .handler(new ClientChannelInitializer()); try { ChannelFuture future = bootstrap.connect(address,port).sync(); future.channel().closeFuture().sync(); } catch (Exception e) { e.printStackTrace(); }finally { group.shutdownGracefully(); } } public static void main(String[] args) { ProtoBufClient client = new ProtoBufClient(7788,"127.0.0.1"); client.start(); } }
Client Initializer:
public class ClientChannelInitializer extends ChannelInitializer<SocketChannel> { protected void initChannel(SocketChannel socketChannel) throws Exception { ChannelPipeline pipeline = socketChannel.pipeline(); pipeline.addLast(new ProtobufVarint32LengthFieldPrepender()); pipeline.addLast(new ProtobufEncoder()); pipeline.addLast(new ProtoBufClientHandler()); } } client handler: public class ProtoBufClientHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { MessageProto.ResponseMsg m = (MessageProto.ResponseMsg)msg; System.out.println("Server say: "+m.getReceiveOne()+","+m.getMsg()); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { MessageProto.RequestMsg.Builder builder = MessageProto.RequestMsg.newBuilder(); builder.setMsgType(ByteString.copyFromUtf8("CBSP")); builder.setReceiveOne("Xiao Ming"); builder.setMsg("Hello, I'm looking for you"); ctx.writeAndFlush(builder.build()); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println("Client is close"); } }
Start the server and client, and the output is as follows:
We have finished the simplest protoBuf application case. The real use scenarios are similar, so we can adapt to the situation.
Recent hot article recommendations:
1.1000 + Java interview questions and answers (2021 latest version)
2.Finally got the IntelliJ IDEA activation code through the open source project. It's really fragrant!
3.Ali Mock tools are officially open source and kill all Mock tools on the market!
4.Spring Cloud 2020.0.0 is officially released, a new and subversive version!
5.Java development manual (Songshan version) is the latest release. Download it quickly!
Feel good, don't forget to like + forward!