Google protobuf for use in Netty

Source: Internet
Author: User

[TOC]

Google protobuf for use in Netty

The code comes from the 8th chapter of the Netty Authoritative guide, which has been annotated, but it is important to note that the use of the proto source code is generated in the beginning and use of Google Protobuf, the use of the PROTOBUF Code Auto-generation tool can refer to this article.

In the example, the ProtobufVarint32FrameDecoder use of decoders and encoders ProtobufVarint32LengthFieldPrepender has already solved the problem of half-pack, which can be commented out when testing, so as to demonstrate the problem of TCP sticky packets using PROTOBUF in Netty.

At the same time, through the use of protobuf can also be deeply felt, its use in the Netty is very simple, codec, half-packet problem, only need to add the relevant processor, and it can easily implement cross-language remote service invocation. (Protobuf itself provides support for different languages)

But in fact, when used, there is a problem, that is, the codec object needs to use its generated specific proto object to operate, that is, Need to write. proto files, and then through the PROTOC to generate the corresponding language code files, obviously this will still be a bit of trouble (although in fact, it is OK, not trouble), there is no convenient way to point it? This problem can be solved by using protostuff later.

Service-Side Subreqserver.java
Package Cn.xpleaf.subscribe;import Cn.xpleaf.protobuf.subscribereqproto;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.codec.protobuf.ProtobufDecoder; Import Io.netty.handler.codec.protobuf.protobufencoder;import Io.netty.handler.codec.protobuf.protobufvarint32framedecoder;import Io.netty.handler.codec.protobuf.protobufvarint32lengthfieldprepender;import Io.netty.handler.logging.LogLevel; Import Io.netty.handler.logging.logginghandler;public class Subreqserver {public void bind (int port) throws Exception        {//Configure the NIO thread group on the server Eventloopgroup bossgroup = new Nioeventloopgroup ();        Eventloopgroup Workergroup = new Nioeventloopgroup ();     try {       Serverbootstrap B = new Serverbootstrap (); B.group (Bossgroup, Workergroup). Channel (nioserversocketchannel.class). Option (channeloption . So_backlog, 1024)//Add log processor. Handler (new Logginghandler (Loglevel.info)). Chi Ldhandler (New channelinitializer<socketchannel> () {@Override protected void I                         Nitchannel (Socketchannel ch) throws Exception {//Add Protobufvarint32framedecoder, mainly used for protobuf half-package processing                        Ch.pipeline (). AddLast (New Protobufvarint32framedecoder ()); Add the Protobufdecoder decoder, its parameters are com.google.protobuf.MessageLite//actually is to tell Protobufdecoder need to decode the target class is what, Otherwise, only from the byte array is//cannot determine the target type information to decode (the server needs to resolve the client request, so it is req) Ch.pipeline (). addlast                        (New Protobufdecoder (SubscribeReqProto.SubscribeReq.getDefaultInstance ())); /* * Code comments from the source, used for PROTOBUF's half-packet processing * * An encoder that prepends the Google Protocol buffers * <a href= "https://developers.google.com/protocol-buffers/docs/encoding?csw=1 #varints ">base * varints</a> integer Length field. For example: * <pre> * before ENCODE (+ bytes) after ENCODE  (302 bytes) * +---------------+ +--------+---------------+ * | Protobuf Data |-------------->| Length |                         Protobuf Data |  * |               (bytes) | |  0XAC02 |                         (bytes) |                         * +---------------+ +--------+---------------+ * </pre> *                        */Ch.pipeline (). AddLast (New Protobufvarint32lengthfieldprepender ()); Add ProtoBufencoder Encoder, so there is no need to manually encode the Subscriberesp ch.pipeline (). AddLast (New Protobufencoder ());                    Add Business Processing Handler ch.pipeline (). AddLast (New Subreqserverhandler ());            }                });            Bind port, synchronization waits successfully channelfuture F = b.bind (port). sync ();        Wait for the service-side listener port to close F.channel (). Closefuture (). sync ();            } finally {//gracefully exits, releasing thread pool resource bossgroup.shutdowngracefully ();        Workergroup.shutdowngracefully ();        }} public static void Main (string[] args) throws Exception {int port = 8080;            if (args! = null && args.length > 0) {try {port = integer.valueof (port); } catch (NumberFormatException e) {//Todo:handle exception}} new Subreqserve    R (). bind (port); }}
Subreqserverhandler.java
Package Cn.xpleaf.subscribe;import Cn.xpleaf.protobuf.subscribereqproto;import Cn.xpleaf.protobuf.subscriberespproto;import Io.netty.channel.channelhandlercontext;import Io.netty.channel.channelinboundhandleradapter;public class Subreqserverhandler extends Channelinboundhandleradapter {/** * because the Protobufdecoder has already decoded the message, so the received order request message can be directly used * To verify the user name, check the post-construction reply message returned to Client, because of the use of Protobufencoder, * so do not need to manually encode the SUBSCRIBERESPPROTO.SUBSCRIBERESP */@Override public void Channelrea D (Channelhandlercontext ctx, Object msg) throws Exception {Subscribereqproto.subscribereq req = (subscribereqproto .        Subscribereq) msg;        String username = req.getusername (); if ("Xpleaf". Equalsignorecase (username)) {System.out.println ("Service Accept client Subscribe req: [" + req.to            String () + "]");        Ctx.writeandflush (RESP (req.getsubreqid ())); }}/** * Build Subscriberespproto.subscriberesp Object * @param subreqid * @return */priVate subscriberespproto.subscriberesp resp (int subreqid) {SubscribeRespProto.SubscribeResp.Builder Builder = subsc        RibeRespProto.SubscribeResp.newBuilder ();        Builder.setsubreqid (SUBREQID);        Builder.setrespcode (0);        Builder.setdesc ("Netty Book Order succeed, 3 days later, sent to the designated address");    return Builder.build (); } @Override public void Exceptioncaught (Channelhandlercontext ctx, throwable cause) {//exception occurred, close link CTX    . Close (); }}
Client Subreqclient.java
Package Cn.xpleaf.subscribe;import Cn.xpleaf.protobuf.subscriberespproto;import Io.netty.bootstrap.Bootstrap; 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.niosocketchannel;import Io.netty.handler.codec.protobuf.protobufdecoder;import Io.netty.handler.codec.protobuf.protobufencoder;import Io.netty.handler.codec.protobuf.protobufvarint32framedecoder;import Io.netty.handler.codec.protobuf.protobufvarint32lengthfieldprepender;import Io.netty.handler.logging.LogLevel; Import Io.netty.handler.logging.logginghandler;public class Subreqclient {public void connect (String host, int port) t        Hrows Exception {//Configure client NIO thread Group Eventloopgroup group = new Nioeventloopgroup ();            try {Bootstrap b = new Bootstrap (); B.group (GrouP). Channel (niosocketchannel.class). Option (Channeloption.tcp_nodelay, True)//Set TCP connection time-out . option (Channeloption.connect_timeout_millis, up). Handler (New Channelinitializer<socket Channel> () {@Override protected void Initchannel (Socketchannel ch) throws Except Ion {//Add Protobufvarint32framedecoder, mainly used for protobuf half-packet processing ch.pipeline (). Addl                        AST (New Protobufvarint32framedecoder ()); Add the Protobufdecoder decoder, its parameters are com.google.protobuf.MessageLite//actually is to tell Protobufdecoder need to decode the target class is what, Otherwise, only from the byte array is//cannot determine the target type information to decode (the client needs to resolve the service-side request, so it is resp) ch.pipeline (). Addlas                        T (new Protobufdecoder (SubscribeRespProto.SubscribeResp.getDefaultInstance ())); /** * Code comment from source, used for PROTOBUF half package processing * * An encoder that PREpends the the The Google Protocol buffers * <a href= "Https://developers.google.com/protocol-buffer S/docs/encoding?csw=1#varints ">base * varints</a> integer Length field. For example: * <pre> * before ENCODE (+ bytes) after ENCODE  (302 bytes) * +---------------+ +--------+---------------+ * | Protobuf Data |-------------->| Length |                         Protobuf Data |  * |               (bytes) | |  0XAC02 |                         (bytes) |                         * +---------------+ +--------+---------------+ * </pre> *                        */Ch.pipeline (). AddLast (New Protobufvarint32lengthfieldprepender ()); Add the Protobufencoder encoder so that you do not need to manually encode the Subscriberesp ch.pipeline (). AddLast (New Protobufencoder ());                    Add Business Processing Handler ch.pipeline (). AddLast (New Subreqclienthandler ());            }                });            Initiates an asynchronous connection operation channelfuture F = b.connect (host, port). sync ();        Wait for the client link to close F.channel (). Closefuture (). sync ();        } finally {//gracefully exits, releasing the NIO thread Group group.shutdowngracefully ();        }} public static void Main (string[] args) throws Exception {int port = 8080;            if (args! = null && args.length > 0) {try {port = integer.valueof (port); } catch (NumberFormatException e) {//takes the default value}} new Subreqclient (). Connect ("Loca    Lhost ", port); }}
Subreqclienthandler.java
Package Cn.xpleaf.subscribe;import Java.util.arraylist;import Java.util.list;import Cn.xpleaf.protobuf.subscribereqproto;import Io.netty.channel.channelhandlercontext;import Io.netty.channel.channelinboundhandleradapter;public class Subreqclienthandler extends Channelinboundhandleradapter {@Override public void channelactive (Channelhandlercontext ctx) {for (int i = 0 ; I < 10;        i++) {ctx.write (Subreq (i));    } ctx.flush (); /** * Build Subscribereqproto.subscribereq Object * @param i * @return */Private SUBSCRIBEREQPROTO.SUBSCRI         Bereq subreq (int i) {SubscribeReqProto.SubscribeReq.Builder Builder = SubscribeReqProto.SubscribeReq.newBuilder ();        Builder.setsubreqid (i);        Builder.setusername ("Xpleaf");        Builder.setproductname ("Netty Book for Protobuf");        list<string> address = new arraylist<> ();        Address.add ("Nanjing Yuhuatai");        Address.add ("Beijing Liulichange"); Address.aDD ("ShenZhen Hongshulin");        Builder.addalladdress (address);    return Builder.build (); } @Override public void Channelread (Channelhandlercontext ctx, Object msg) throws Exception {System.out.prin    TLN ("Service Accept Server Subscribe response: [" + msg + "]");    } @Override public void Channelreadcomplete (Channelhandlercontext ctx) throws Exception {Ctx.flush (); } @Override public void Exceptioncaught (Channelhandlercontext ctx, Throwable cause) throws Exception {cause.        Printstacktrace ();    Ctx.close (); }}
Test

The server output is as follows:

Service Accept Client Subscribe req: [subreqid:0username: "Xpleaf" ProductName: "Netty Book for Protobuf" Address: "Nanjin G Yuhuatai "Address:" Beijing Liulichange "Address:" ShenZhen Hongshulin "]service Accept Client Subscribe req: [subreqid:1 UserName: "Xpleaf" ProductName: "Netty Book for Protobuf" Address: "Nanjing Yuhuatai" Address: "Beijing Liulichange" Address: "ShenZhen Hongshulin"]service Accept Client Subscribe req: [subreqid:2username: "Xpleaf" ProductName: "Netty Boo K for Protobuf "address:" Nanjing Yuhuatai "Address:" Beijing Liulichange "Address:" ShenZhen Hongshulin "]service Accept Client Subscribe req: [subreqid:3username: "Xpleaf" ProductName: "Netty Book for Protobuf" Address: "Nanjing Yuhuatai" addr ESS: "Beijing Liulichange" Address: "ShenZhen Hongshulin"]service Accept Client Subscribe req: [subreqid:4username: "Xple AF "ProductName:" Netty Book for Protobuf "Address:" Nanjing Yuhuatai "Address:" Beijing Liulichange "Address:" ShenZhen Hongshulin "]service Accept client SubscribE req: [subreqid:5username: "Xpleaf" ProductName: "Netty Book for Protobuf" Address: "Nanjing Yuhuatai" Address: "Beijing L Iulichange "Address:" ShenZhen Hongshulin "]service Accept Client Subscribe req: [subreqid:6username:" Xpleaf " ProductName: "Netty Book for Protobuf" Address: "Nanjing Yuhuatai" Address: "Beijing Liulichange" Address: "ShenZhen Hongshulin "]service Accept Client Subscribe req: [subreqid:7username:" Xpleaf "ProductName:" Netty book for Protobuf "addr  ESS: "Nanjing Yuhuatai" Address: "Beijing Liulichange" Address: "ShenZhen Hongshulin"]service Accept client Subscribe req: [Subreqid:8username: "Xpleaf" ProductName: "Netty Book for Protobuf" Address: "Nanjing Yuhuatai" Address: "Beijing Liulich Ange "Address:" ShenZhen Hongshulin "]service Accept Client Subscribe req: [subreqid:9username:" Xpleaf "ProductName:" Net Ty Book for Protobuf "Address:" Nanjing Yuhuatai "Address:" Beijing Liulichange "Address:" ShenZhen Hongshulin "]

The

Client output is as follows:

Service Accept Server Subscribe response: [SUBREQID:0RESPCODE:0DESC: "Netty book Order succeed, 3 days later, sent to T He designated address "]service Accept Server Subscribe response: [SUBREQID:1RESPCODE:0DESC:" Netty book Order Succeed, 3 days later, sent to the designated address "]service Accept Server Subscribe response: [SUBREQID:2RESPCODE:0DESC:" Net  Ty book Order succeed, 3 days later, sent to the designated address "]service Accept Server Subscribe response: [SUBREQID: 3respcode:0desc: "Netty book Order succeed, 3 days later, sent to the designated address"]service Accept server Subscrib  E response: [Subreqid:4respcode:0desc: "Netty book Order succeed, 3 days later, sent to the designated address"]service Accept Server Subscribe response: [SUBREQID:5RESPCODE:0DESC: "Netty book Order succeed, 3 days later, sent to the Desi gnated Address "]service Accept Server Subscribe response: [SUBREQID:6RESPCODE:0DESC:" Netty book Order succeed, 3 days Later, sent to the Designated Address "]service Accept Server Subscribe response: [SUBREQID:7RESPCODE:0DESC:" Netty book Order succeed, 3 days L Ater, sent to the designated address "]service Accept Server Subscribe response: [SUBREQID:8RESPCODE:0DESC:" Netty book Order succeed, 3 days later, sent to the designated address "]service Accept Server Subscribe response: [Subreqid:9respco De:0desc: "Netty book Order succeed, 3 days later, sent to the designated address"]

Google protobuf use in Netty

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.