Application of Messagepack in Netty

Source: Internet
Author: User
Tags throwable

[TOC]

Application of Messagepack in Netty

In front of the Netty communication, the transfer is a string object, because when making a remote procedure call, more of the transfer Pojo object, then need to serialize and deserialize the Pojo object (encoding and decoding), because of the limitations of the Java serialization technology itself, The third-party codec framework is often used, such as the messagepack used here.

There are two points to note when using Messagepack:

    • The result of Messagepack encoding is a list object;
    • The transmission of the Pojo object must be added @message annotations, or can not be encoded using Messagepack;

The above two is really very important, I first used messagepack in the Netty, because did not pay attention to the above two points, write Netty program run no error, client connection service is not a problem, but is not output transmission Pojo object, the reason is the above two problems, So be sure to first know the two-point principle, otherwise there will be a lot of problems in testing the Netty program, and troubleshooting the debug process is not easy.

The code for the demo is given here, because there are a lot of comments in the code, so this is no longer explained in detail.

Encoder and Decoder Msgpackencoder.java
package cn.xpleaf.msgpack;import org.msgpack.MessagePack;import io.netty.buffer.ByteBuf;import io.netty.channel.ChannelHandlerContext;import io.netty.handler.codec.MessageToByteEncoder;/** * MsgpackEncoder继承自Netty中的MessageToByteEncoder类, * 并重写抽象方法encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) * 它负责将Object类型的POJO对象编码为byte数组,然后写入到ByteBuf中 * @author yeyonghao * */public class MsgpackEncoder extends MessageToByteEncoder<Object> {    @Override    protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {        // 创建MessagePack对象        MessagePack msgpack = new MessagePack();        // 将对象编码为MessagePack格式的字节数组        byte[] raw = msgpack.write(msg);        // 将字节数组写入到ByteBuf中        out.writeBytes(raw);    }}
Msgpackdecoder
Package Cn.xpleaf.msgpack;import Java.util.list;import Org.msgpack.messagepack;import io.netty.buffer.ByteBuf; Import Io.netty.channel.channelhandlercontext;import Io.netty.handler.codec.bytetomessagedecoder;import io.netty.handler.codec.messagetomessagedecoder;/** * Msgpackdecoder inherits from the Messagetomessagedecoder class in Netty, * and rewrite the abstract method decode (Channelhandlercontext ctx, Bytebuf msg, list<object> out) * First get the byte array that needs to be decoded from the datagram msg (the type of data that is populated when the Messagetomessagedecoder is inherited) * and then call Messagepack's Read method to deserialize it (decode) to Object * The decoded object is added to the Decode list out, which completes the decoding operation of the messagepack * @author Yeyonghao * */public class Msgpackdecoder extends messagetomessagedecoder<bytebuf> {@Override protected void decode (Channelhandlercontext ctx, Bytebuf msg, Lis T<object> out) throws Exception {//From datagram MSG (data Type here is BYTEBUF, because Netty communication is based on Bytebuf object) final byte[] Arra        Y        Final int length = Msg.readablebytes ();        Array = new Byte[length]; /** * Here is the Bytebuf GetBytes method used to convert the Bytebuf object to a wordSection array, preceded by the use of readbytes, directly passed in a received byte array parameter can be * Here the parameters are more, the first parameter is index, about Readerindex, described as follows: * Bytebuf is through Readerindex and WR Iterindex two position pointer to assist the buffer read and write operation, the specific principle wait until Netty source code analysis and then learn in detail * The second parameter is the byte array received * The third parameter is Dstindex the first index of th E destination * The fourth parameter is the length of the number of bytes to transfer */Msg.getbytes (Msg.readerindex (), a        Rray, 0, length);        Create a Messagepack object messagepack msgpack = new Messagepack ();    Decode and add to decode list out in Out.add (Msgpack.read (array)); }}
Service-Side Pojoserver.java
Package Cn.xpleaf.basic;import Cn.xpleaf.msgpack.msgpackdecoder;import Cn.xpleaf.msgpack.msgpackencoder;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;public class Pojoserver {public void bind (int port) throws Exceptio        n {eventloopgroup bossgroup = new Nioeventloopgroup ();        Eventloopgroup Workergroup = new Nioeventloopgroup ();            try {serverbootstrap b = new Serverbootstrap (); B.group (Bossgroup, Workergroup). Channel (nioserversocketchannel.class). Option (channeloption . So_backlog, 1024x768). Childhandler (New channelinitializer<socketchannel> () {@Overrid E protected void Initchannel (Socketchannel ch) throws Exception {//Add Messpagepack Decoder                        Ch.pipeline (). AddLast ("Msgpack decoder", New Msgpackdecoder ());                        Add Messagepack Encoder Ch.pipeline (). AddLast ("Msgpack encoder", New Msgpackencoder ());                    Add Business Processing Handler ch.pipeline (). AddLast (New Pojoserverhandler ());            }                });            Bind port, the synchronization waits successfully, the method is synchronous blocking, the binding succeeds and returns a channelfuture channelfuture f = b.bind (port). sync ();        Wait for the service-side listener port to close, block, wait for the service-side link to close after the main function exits 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 Pojoserver ()    . bind (port); }}
Pojoserverhandler.java
package cn.xpleaf.basic;import java.util.List;import cn.xpleaf.pojo.User;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelInboundHandlerAdapter;public class PojoServerHandler extends ChannelInboundHandlerAdapter {    @Override    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {        // 注意msg为List,而不是User类型,这点尤其需要注意        // 否则程序人执行,不会报错,但没有任何输出        @SuppressWarnings("unchecked")        List<Object> list = (List<Object>) msg;        System.out.println("Pojo from client : " + list);        // 遍历List,输出的是pojo对象中的属性        for (Object obj : list) {            System.out.println(obj);        }    }    @Override    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {        ctx.flush();    }    @Override    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {        ctx.close();    }}
Client Pojoclient.java
Package Cn.xpleaf.basic;import Cn.xpleaf.msgpack.msgpackdecoder;import Cn.xpleaf.msgpack.msgpackencoder;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;public class Pojoclient {public void connect (int port, String host) throw        s 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, Handler). New Channelinitializ Er<socketchannel> () {@Override proteCTED void Initchannel (Socketchannel ch) throws Exception {//Add Messpagepack Decoder                        Ch.pipeline (). AddLast ("Msgpack decoder", New Msgpackdecoder ());                        Add Messagepack Encoder Ch.pipeline (). AddLast ("Msgpack encoder", New Msgpackencoder ());                    Add Business Processing Handler ch.pipeline (). AddLast (New Pojoclienthandler ());            }                });            Initiates an asynchronous connection operation (Note that the server is bind and the client needs connect) 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) {             Take the default value}} new Pojoclient (). Connect (port, "localhost"); }}
Pojoclienthandler.java
package cn.xpleaf.basic;import cn.xpleaf.pojo.User;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelInboundHandlerAdapter;public class PojoClientHandler extends ChannelInboundHandlerAdapter {    @Override    public void channelActive(ChannelHandlerContext ctx) {        User user = new User();        user.setName("client");        user.setAge(10);//      for(int i = 0; i < 10; i++) {//          ctx.write(user);//      }//      ctx.flush();        ctx.writeAndFlush(user);    }    @Override    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {    }    @Override    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {        ctx.flush();    }    @Override    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {        ctx.close();    }}
Pojouser.java
package cn.xpleaf.pojo;import org.msgpack.annotation.Message;@Messagepublic class User {    private String name;    private int age;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    @Override    public String toString() {        return "User [name=" + name + ", age=" + age + "]";    }}
Test

Run the service side, and then run the client, the output of the server is as follows:

Pojo from client : ["client",10]"client"10

Application of Messagepack 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.