Read the "Netty Authority Guide" book, the 14th chapter with the entire chapter describes how to design and implement a simple private protocol, the content is good, but the author provided a lot of code snippets error, it is impossible to compile correctly.
For example Marshallingencoder This class is Netty provides an adaptive class of JBoss marshalling, its Encode method is protected, not public, And the Channelbufferbyteoutput class used is the package class is visible and cannot be referenced externally. Netty is only so designed because the tool class cannot be used directly from the outside, but only for internal Channelhandler. You must inherit it if you want to use it externally. But the code in the book directly uses ... Do not know how to compile the pass.
In addition Nettymessageencoder inside the calculation message length code also has no problem, Nettymessagedecoder did not set lengthadjustment, it is impossible to run successfully, do not know the results of the book in the screenshot how to obtain.
Had to change the code in the book, and in the local run successfully, the implementation of the message structure definition, message codec class, JBoss marshalling encoder/decoder extension, Loginreqhandler/ Loginreshandler, Nettyserver, Nettyclient. Now put the code out, there is a need for students to take a run in the local.
Define message nettymessage and message header header
Package com.netty.test.netty4;
public class Nettymessage {
private header header;
Private Object body;
Public header GetHeader () {return
header;
}
public void SetHeader (header header) {
This.header = header;
}
Public Object GetBody () {return body
;
}
public void Setbody (Object body) {
this.body = body;
}
Public String toString () {return
"Nettymessage [header=" + header + "]";
}
}
Package com.netty.test.netty4;
Import Java.util.HashMap;
Import Java.util.Map;
public class Header {private int crccode = 0xabef0101;
private int length;
Private long SessionID;
private byte type;
private byte priority;
Private map<string, object> attachment = new hashmap<string, object> ();
public int Getcrccode () {return crccode;
The public void Setcrccode (int crccode) {this.crccode = Crccode;
public int GetLength () {return length;
public void SetLength (int length) {this.length = length;
Public long GetSessionID () {return sessionID;
} public void Setsessionid (long SessionID) {This.sessionid = SessionID;
Public byte GetType () {return type;
The public void SetType (byte type) {This.type = type;
Public byte getpriority () {return priority;
} public void SetPriority (Byte priority) {this.priority = priority;
Public map<string, Object> getattachment () {return attachment; } public VOID Setattachment (map<string, object> attachment) {this.attachment = attachment;
Public String toString () {return Header [crccode= "+ Crccode +", length= "+ length +", sessionid= "+ SessionID
+ ", type=" + Type + ", priority=" + priority + ", attachment=" + attachment + "]; }
}
Extending Marshallingencoder and Marshallingdecoder, the protected method programming public can call the
Package com.netty.test.netty4;
Import Io.netty.buffer.ByteBuf;
Import Io.netty.channel.ChannelHandlerContext;
Import Io.netty.handler.codec.marshalling.MarshallerProvider;
Import Io.netty.handler.codec.marshalling.MarshallingEncoder;
public class Nettymarshallingencoder extends marshallingencoder{public
Nettymarshallingencoder ( Marshallerprovider provider) {
super (provider);
}
public void Encode (Channelhandlercontext ctx, Object msg, bytebuf out) throws exception{
(Super.encode, MSG, out);
}
}
Package com.netty.test.netty4;
Import Io.netty.buffer.ByteBuf;
Import Io.netty.channel.ChannelHandlerContext;
Import Io.netty.handler.codec.marshalling.MarshallingDecoder;
Import Io.netty.handler.codec.marshalling.UnmarshallerProvider;
public class Nettymarshallingdecoder extends marshallingdecoder{public
Nettymarshallingdecoder ( Unmarshallerprovider provider) {
super (provider);
}
Public Nettymarshallingdecoder (unmarshallerprovider provider, int maxobjectsize) {
super (provider, maxobjectsize );
}
Public Object decode (Channelhandlercontext ctx, bytebuf in) throws Exception {return
Super.decode (CTX, in);
}
Define the Marshallingcodecfactory factory class to get the JBoss marshalling class
Package com.netty.test.netty4;
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.UnmarshallerProvider;
Import Org.jboss.marshalling.MarshallerFactory;
Import org.jboss.marshalling.Marshalling;
Import org.jboss.marshalling.MarshallingConfiguration; public class Marshallingcodecfactory {public static Nettymarshallingdecoder Buildmarshallingdecoder () {marshallerfact
Ory marshallerfactory = marshalling.getprovidedmarshallerfactory ("Serial");
Marshallingconfiguration configuration = new Marshallingconfiguration ();
Configuration.setversion (5);
Unmarshallerprovider Provider = new Defaultunmarshallerprovider (marshallerfactory, configuration);
Nettymarshallingdecoder decoder = new Nettymarshallingdecoder (provider, 1024); Return Decoder public static Nettymarshallingencoder Buildmarshallingencoder () {marshallerfactory marshallerfactory = Marshalling.
Getprovidedmarshallerfactory ("Serial");
Marshallingconfiguration configuration = new Marshallingconfiguration ();
Configuration.setversion (5);
Marshallerprovider Provider = new Defaultmarshallerprovider (marshallerfactory, configuration);
Nettymarshallingencoder encoder = new Nettymarshallingencoder (provider);
Return encoder;
}
}
Define the encoder of the nettymessage, pay attention to the method of calculating the length of messages, and finally pass the message out
Package com.netty.test.netty4;
Import Io.netty.buffer.ByteBuf;
Import io.netty.buffer.Unpooled;
Import Io.netty.channel.ChannelHandlerContext;
Import Io.netty.handler.codec.MessageToMessageEncoder;
Import java.util.List;
Import Java.util.Map; public class Nettymessageencoder extends messagetomessageencoder<nettymessage>{private
Nettymarshallingencoder Marshallingencoder;
Public Nettymessageencoder () {marshallingencoder = Marshallingcodecfactory.buildmarshallingencoder (); @Override protected void Encode (Channelhandlercontext ctx, Nettymessage msg, list<object> out) throws Excep
tion {if (msg = NULL | | msg.getheader () = null) {throw new Exception ("The ENCODE message is null");
} bytebuf SendBuf = Unpooled.buffer ();
Sendbuf.writeint (Msg.getheader (). Getcrccode ());
Sendbuf.writeint (Msg.getheader (). GetLength ());
Sendbuf.writelong (Msg.getheader (). GetSessionID ());
Sendbuf.writebyte (Msg.getheader (). GetType ()); Sendbuf.writebyte (Msg.getheadER (). getpriority ());
Sendbuf.writeint (Msg.getheader (). GetAttachment (). Size ());
String key = null;
byte[] Keyarray = null;
Object value = null;
For (map.entry<string, object> param:msg.getHeader (). GetAttachment (). EntrySet ()) {key = Param.getkey ();
Keyarray = Key.getbytes ("UTF-8");
Sendbuf.writeint (keyarray.length);
Sendbuf.writebytes (Keyarray);
Value = Param.getvalue ();
Marshallingencoder.encode (CTX, value, SENDBUF);
} key = null;
Keyarray = null;
value = NULL;
if (msg.getbody ()!= null) {Marshallingencoder.encode (CTX, Msg.getbody (), sendbuf);
}//Sendbuf.writeint (0);
In the 4th byte the length of the write buffer is int readablebytes = Sendbuf.readablebytes ();
Sendbuf.setint (4, readablebytes);
Add the message to the list and pass it to the next handler Out.add (SENDBUF);
}
}
Define the Nettymessagedecoder class, pay attention to set the lengthfieldbasedframedecoder of several important parameters, directly affect the decoding results
Package com.netty.test.netty4;
Import Io.netty.buffer.ByteBuf;
Import Io.netty.channel.ChannelHandlerContext;
Import Io.netty.handler.codec.LengthFieldBasedFrameDecoder;
Import Java.util.HashMap;
Import Java.util.Map; public class Nettymessagedecoder extends lengthfieldbasedframedecoder{private Nettymarshallingdecoder
Marshallingdecoder; Public Nettymessagedecoder (int maxframelength, int lengthfieldoffset, int lengthfieldlength,int lengthadjustment, int i Nitialbytestostrip) {super (maxframelength, Lengthfieldoffset, Lengthfieldlength, Lengthadjustment,
Initialbytestostrip);
Marshallingdecoder = Marshallingcodecfactory.buildmarshallingdecoder (); The public Object decode (Channelhandlercontext ctx, bytebuf in) throws exception{the bytebuf frame = (bytebuf) super.decod
E (CTX, in);
if (frame = = null) {return null;
} nettymessage message = new Nettymessage ();
Header Header = new header ();
Header.setcrccode (Frame.readint ());
Header.setlength (Frame.readint ()); Header.setsessionid (Frame.readlong ());
Header.settype (Frame.readbyte ());
Header.setpriority (Frame.readbyte ());
int size = Frame.readint ();
if (Size > 0) {map<string, object> attach = new hashmap<string, object> (size);
int keysize = 0;
byte[] Keyarray = null;
String key = null;
for (int i=0; i<size; i++) {keysize = Frame.readint ();
Keyarray = new Byte[keysize];
In.readbytes (Keyarray);
Key = new String (Keyarray, "UTF-8");
Attach.put (Key, Marshallingdecoder.decode (CTX, frame));
} key = null;
Keyarray = null;
Header.setattachment (attach);
} if (Frame.readablebytes () > 0) {message.setbody (Marshallingdecoder.decode (CTX, frame));
} message.setheader (header);
return message;
}
}
Define Loginauthreqhandler, the client sends the requested business Channelhandler
Package com.netty.test.netty4;
Import Io.netty.channel.ChannelHandlerAdapter;
Import Io.netty.channel.ChannelHandlerContext; public class Loginauthreqhandler extends Channelhandleradapter {public void channelactive (Channelhandlercontext ctx) th
Rows Exception {Ctx.writeandflush (Buildloginreq ()); } public void Channelread (Channelhandlercontext ctx, Object msg) throws Exception {nettymessage message = (nettyme
ssage) msg; if (Message.getheader ()!= null && message.getheader (). GetType () = (byte) 2) {System.out.println ("Received from
Server Response ");
Ctx.firechannelread (msg);
Private Nettymessage Buildloginreq () {nettymessage message = new Nettymessage ();
Header Header = new header ();
Header.settype ((byte) 1);
Message.setheader (header);
Message.setbody ("It is Request");
return message;
public void Channelreadcomplete (Channelhandlercontext ctx) throws Exception {Ctx.flush (); } public void exceptioncaught (Channelhandlercontext ctX, Throwable cause) {ctx.close ();
}
}
Define Loginauthresphandler class, server-side response login's business Channelhandler
Package com.netty.test.netty4;
Import Io.netty.channel.ChannelHandlerAdapter;
Import Io.netty.channel.ChannelHandlerContext; public class Loginauthresphandler extends Channelhandleradapter {public void Channelread (Channelhandlercontext ctx, Ob
Ject msg) throws Exception {nettymessage message = (nettymessage) msg;
if (Message.getheader ()!= null && message.getheader (). GetType () = = (byte) 1) {System.out.println ("Login is OK");
String BODY = (string) message.getbody ();
SYSTEM.OUT.PRINTLN ("recevied message body from the client is" + body);
} Ctx.writeandflush (Buildloginresponse ((byte) 3));
Private Nettymessage Buildloginresponse (byte result) {Nettymessage message = new Nettymessage ();
Header Header = new header ();
Header.settype ((byte) 2);
Message.setheader (header);
Message.setbody (result);
return message;
public void Channelreadcomplete (Channelhandlercontext ctx) throws Exception {Ctx.flush (); } public void Exceptioncaught (ChannelhandLercontext CTX, Throwable cause) {ctx.close ();
}
}
Define Nettyclient
Package com.netty.test.netty4;
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.LineBasedFrameDecoder;
Import Io.netty.handler.codec.string.StringDecoder; public class Nettyclient {public void connect (String remoteserver, int port) throws Exception {Eventloopgroup Workerg
Roup = new Nioeventloopgroup ();
try {Bootstrap b = new Bootstrap ();
B.group (Workergroup). Channel (Niosocketchannel.class). Handler (new Childchannelhandler ());
Channelfuture f = b.connect (Remoteserver,port). sync ();
System.out.println ("Netty time Client connected at Port" + port);
F.channel (). Closefuture (). sync (); finally {workergroup.shutdowngracefully (); } public static class Childchannelhandler extends Channelinitializer<socketchannel> {@Override protect Ed void Initchannel (Socketchannel ch) throws Exception {//-8 means lengthadjustment, allowing the decoder to intercept bytes from 0 and include the message header Ch.pipeline (). AddLast (New Nettymessagedecoder (1024 * 1024, 4, 4,-8, 0)). AddLast (New Nettymessageencoder ()). AddLast (New Loginaut
Hreqhandler ());
} public static void Main (string[] args {try {new nettyclient (). Connect ("127.0.0.1", 9080);
catch (Exception e) {e.printstacktrace ();
}
}
}
Define Nettyserver
Package com.netty.test.netty4;
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.LineBasedFrameDecoder;
Import Io.netty.handler.codec.string.StringDecoder; public class Nettyserver {public void bind (int port) throws Exception {Eventloopgroup Bossgroup = new Nioeventloopgro
Up ();
Eventloopgroup Workergroup = new Nioeventloopgroup ();
try {serverbootstrap b = new Serverbootstrap ();
B.group (Bossgroup, Workergroup). Channel (nioserversocketchannel.class). Option (Channeloption.so_backlog, 1024)
. Childhandler (New Childchannelhandler ());
Channelfuture f = b.bind (port). sync (); System.out.println ("Netty Time Server started aT Port "+ port";
F.channel (). Closefuture (). sync ();
finally {bossgroup.shutdowngracefully ();
Workergroup.shutdowngracefully (); } public static class Childchannelhandler extends Channelinitializer<socketchannel> {@Override protect Ed void Initchannel (Socketchannel ch) throws Exception {Ch.pipeline (). AddLast (New Nettymessagedecoder (1024 * 1024, 4,
4,-8, 0)). AddLast (New Nettymessageencoder ()). AddLast (New Loginauthresphandler ());
} public static void Main (string[] args) {try {new nettyserver (). bind (9080);
catch (Exception e) {e.printstacktrace ();
}
}
}
Run Result:
Server side:
Client:
Running a dependent jar package
Sample code Download
Http://pan.baidu.com/s/1kT1PwO3