Before we learn netty, we need to know what Netty is, Netty is a high-performance, asynchronous event-driven NIO framework that provides support for TCP, UDP, and file transfer, primarily providing asynchronous, event-driven network application frameworks and tools for rapidly developing high-performance, High-Reliability network server and client programs.
You can use Netty as a communication tool, and you can have it all involved in network communications, as well as Mina Netty.
Protocolbuffer is a Google format for data interchange, independent of language, platform-independent, and Google offers a variety of language implementations: Java, C #, C + +, go, and Python, each of which contains compilers for the language and library files. Protobuf can be treated as a carrier of encapsulated data.
Here's the syntax address for PROTOBUF.
http://blog.csdn.net/sylar_d/article/details/51325987
Actually, it's the domain that really works.
When we define the message, PROTOBUF provides 3 optional domains:
Required:message must contain at least one required field and must be assigned before serialization.
You need to include more than 0 optional domains in Optional:message.
Repeated: This field is used to save some variables that you want to set repeatedly, and these variables can be set up 0 times to multiple times. And the order is saved. (Used to set the array).
We can think of a message as a Java object, where required and option can be treated as constants, required cannot be null, option can be empty, and repeated can be viewed as a list.
Let's use a simple example.
First create the Protobuf file User.proto
Package test;
Option Java_package = "Com.zengame.proto.user";
Option Java_outer_classname = "Userproto";
Message req_updatesecuritypassword{
Required String securitypassword = 1;
Optional String Oldsecuritypassword = 2[default = ""];//Old password
} message
ans_recommendserver{
required Recommendsvrid = 1;//recommended ServerID player may have information in other suits
} message
req_user{
Required String username = 1;
}
This is the proto file, and the Java compiler is used to generate the code, which is specified below (note: Must be in the same directory):
protoc.exe-i=./--java_out=./proto user.proto
Pause
When we use Proto, we serialize it and deserialize it, so I created a rpcmessage as the object that passed the message, and the code is as follows: Rpcmessage.java
Remember to add this tag and still implement the Serializable interface @Message public class Rpcmessage implements serializable{private static final long Seri
Alversionuid = 1L; private int cmd; Used to store the protocol number private byte[] data;//used to store the PROTOBUF byte array private int seq; Message Queuing location Private byte type;//message type private transient Object obj;//This is temporarily useless, so add transient so that he does not need to serialize public int get
CMD () {return cmd;
public void setcmd (int cmd) {this.cmd = cmd;
Byte[] GetData () {return data;
public void SetData (byte[] data) {this.data = data;
public int Getseq () {return seq;
public void setseq (int seq) {this.seq = seq;
Public byte GetType () {return type;
The public void SetType (byte type) {This.type = type;
Public Object Getobj () {return obj;
public void Setobj (Object obj) {this.obj = obj;
@Override public String toString () { Return "Rpcmessage [cmd=" + cmd + ", seq=" + seq + ", type=" + Type + "]"; }
}
Server Code Nettyserver.java
Serverbootstrap bootStrap = new Serverbootstrap (New Nioserversocketchannelfactory (
Executors.newcachedthreadpool (), Executors.newcachedthreadpool ()); Bootstrap.setpipelinefactory (New Channelpipelinefactory () {@Override public channelpipeline GETP Ipeline () throws Exception {//TODO auto-generated method stub Channelpipeline pipeline =
Channels.pipeline (); Objectdecoder Objectdecoder = new Objectdecoder (1024 * 1024, Classresolvers.weakcachingconcurrentresolver (
This.getclass (). getClassLoader ());
Pipeline.addlast ("Decoder", New Protobufdecoder (UserProto.Ans_RecommendServer.getDefaultInstance ())); Pipeline.addlast ("Decoder", objectdecoder); The transfer object needs to decode Pipeline.addlast ("encoder", New Objectencoder ()) with object decoding; Transfer objects need to use object//pipeline.addlast ("Decoder", new PROTOBUFDEcoder (UserProto.Req_UpdateSecurityPassword.getDefaultInstance ()));
Pipeline.addlast ("encoder", New Protobufencoder ()); Pipeline.addlast ("Handler", New Objectserverhandler ());
The event handler needs to rewrite the return pipeline itself;
}
}); Bootstrap.bind (New inetsocketaddress (8000));
Server Processing Class Objectserverhandler.java
The public class Objectserverhandler extends simplechannelhandler{//Client Connection server executes @Override public void CHANNELC Onnected (Channelhandlercontext ctx, channelstateevent e) throws Exception {//channel store up Pl
Ayermanager.addsession (100175, Ctx.getchannel ()); }//The server will execute @Override public void messagereceived (Channelhandlercontext ctx, messageevent e) When it receives the message
Throws Exception {rpcmessage message = (rpcmessage) e.getmessage (); Switch (Message.getcmd ()) {case 10001:req_updatesecuritypassword ans = REQ_UPDATESECURITYPASSWORD.PA
Rsefrom (Message.getdata ());
SYSTEM.OUT.PRINTLN (message); System.out.println ("Securitypassword =" +ans.getsecuritypassword () + ", Oldsecuritypassword =" +
Ans.getoldsecuritypassword ());
Ans_recommendserver req = Ans_recommendserver.newbuilder (). Setrecommendsvrid (10001) . build ();
Playermanager.sendmessage (Message.getcmd (), Req.tobytearray (), 100175);
Break
Case 10002:req_user RSP = Req_user.parsefrom (Message.getdata ());
SYSTEM.OUT.PRINTLN (message);
System.out.println ("username=" + rsp.getusername ());
req = Ans_recommendserver.newbuilder (). Setrecommendsvrid (10002). build ();
Playermanager.sendmessage (Message.getcmd (), Req.tobytearray (), 100175);
Break
Default:break; }
}
}
Client code Nettyclient.java
Clientbootstrap bootstarp = new Clientbootstrap (New Nioclientsocketchannelfactory (
Executors.newcachedthreadpool (), Executors.newcachedthreadpool ()); Bootstarp.setpipelinefactory (New Channelpipelinefactory () {@Override public channelpipeline GETP Ipeline () throws Exception {//TODO auto-generated method stub Channelpipeline pipeline =
Channels.pipeline (); Objectdecoder Objectdecoder = new Objectdecoder (1024 * 1024, CLASSRESOLVERS.WEAKCACHINGCONCURRENTR
Esolver (this. getclass (). getClassLoader ()));
Pipeline.addlast ("Decoder", New Protobufdecoder (UserProto.Ans_RecommendServer.getDefaultInstance ()));
Pipeline.addlast ("Decoder", objectdecoder);
Pipeline.addlast ("encoder", New Objectencoder ()); Pipeline.addlast ("Handler", New OBjectclienthandler ());
Client processing class return pipeline;
}
}); Bootstarp.connect (New Inetsocketaddress ("127.0.0.1", 8000));
Client-side processing class Objectclienthandler.java
public class Objectclienthandler extends Simplechannelhandler {@Override public void messagereceived (Channelhand
Lercontext CTX, Messageevent e) throws Exception {rpcmessage message = (rpcmessage) e.getmessage (); Switch (Message.getcmd ()) {case 10001:ans_recommendserver Ans = Ans_recommendserver.parsefrom
(Message.getdata ());
SYSTEM.OUT.PRINTLN (message);
System.out.println ("Recommendsvrid =" + Ans.getrecommendsvrid ());
Break
Case 10002:ans = Ans_recommendserver.parsefrom (Message.getdata ());
SYSTEM.OUT.PRINTLN (message);
System.out.println ("Recommendsvrid =" + Ans.getrecommendsvrid ());
Break
Default:break; @Override public void channelconnected (Channelhandlercontext ctx, channelstateevent e) throws
Exception {playermanager.addsession (100175, Ctx.getchannel ()); }
}
Client sends message code
int op = 0;
Scanner in = new Scanner (system.in);
StringBuffer sb = new StringBuffer ();
Boolean flag = true;
do{System.out.println ("Please enter the operation: 1 send message 2 disconnect");
op = in.nextint ();
Switch (OP) {case 1:system.out.print ("Please enter content to send message:");
Sb.append (In.next () + "" +in.next ());
string[] Value = sb.tostring (). Split (""); Req_updatesecuritypassword Req = Req_updatesecuritypassword.newbuilder ().
Setsecuritypassword (Value[0]). Setoldsecuritypassword (value[1))
. build ();
Playermanager.sendmessage (10001,req.tobytearray (), 100175);
Break
Case 2:system.out.print ("Please enter the content to send the message:");
Sb.setlength (0);
Sb.append (In.next ());Req_user username = Req_user.newbuilder (). Setusername (Sb.tostring ())
. build ();
Playermanager.sendmessage (10002,username.tobytearray (), 100175);
Break
Default:PlayerManager.close (100175);
SYSTEM.OUT.PRINTLN ("Connection closed!");
flag =!flag;
Break
}}while (flag); SYSTEM.OUT.PRINTLN ("System shutdown");
Here I do one more step, store channel, file name is Playermanager.java
public class Playermanager {private static map<integer,channel> Sessionmap = new Concurrenthashmap<integer,
Channel> (); public static void Addsession (int playerid, Channel Channel) {if (Sessionmap.containskey (playerID)) {if (Sessionmap.get (playerID) = = Channel)
{return;
} sessionmap.put (playerID, channel); public static void removesession (int playerid) {if (Sessionmap.containskey (playerID)) {Sessionma
P.remove (playerID); }} public static Channel getsession (int playerid) {if (!sessionmap.containskey (playerID)) {RE
Turn null;
Return Sessionmap.get (playerID);
public static void SendMessage (int cmd, byte[] data, int playerID) {if (Sessionmap.containskey (playerID)) {
Rpcmessage message = new Rpcmessage ();
Message.setcmd (CMD);
Message.setseq (-1); Message.settyPE ((Byte)-1);
Message.setdata (data);
Sessionmap.get (playerID). write (message);
SYSTEM.OUT.PRINTLN ("Send message succeeded."); } public static void close (int playerid) {if (Sessionmap.containskey (playerID)) {Sessionmap.
Get (playerID). Close (); }
}
}
Run results
Well, the whole general use should be, with these, I feel can realize a simple chat room system, haha
I would also like to say sorry, because I do not know Netty and NiO is not very deep, but I can recommend this article, is to explain NIO, personally feel very good explanation.
https://zhuanlan.zhihu.com/p/23488863
Summary: Personally feel for the Netty will only be preliminary use, the bottom of the implementation of what I do not know very well, the road of learning never cease.