In the previous blog post, there are ways to split messages with newline characters. However, this method has a small problem, if the message itself contains a newline character, it will split the message into two, the result is wrong.
This article introduces another way of message segmentation, which is the 2nd article in the previous blog post: Use a fixed length header that indicates the length of the body, with a fixed number of bytes in the header prefix to specify the number of bytes in the body, To split the message.
The header in the figure above is fixed to 4 bytes, and the header holds a 4-byte (32-bit) integer, such as 12, which is 0x0000000c, which is used to specify the length of the body (in bytes). After reading so many bytes of body, it is the header of the next message.
The following respectively with Mina, Netty, twisted to achieve this kind of message and decoding.
MINA:
Mina provides prefixedstringcodecfactory to encode this type of message, prefixedstringcodecfactory the default header size is 4 bytes, and of course can be specified as 1 or 2.
public class TCPServer {public static void main (string[] args) throws IOException {Ioacceptor acceptor = new Niosocketacce Ptor ();///4-byte header specifies the number of bytes of the body, the processing of such messages Acceptor.getfilterchain (). AddLast ("Codec", New Protocolcodecfilter (new Prefixedstringcodecfactory (Charset.forname ("UTF-8"))); Acceptor.sethandler (new Tcpserverhandle ()); Acceptor.bind (New inetsocketaddress (8080));}} Class Tcpserverhandle extends Iohandleradapter {@Overridepublic void Exceptioncaught (iosession session, Throwable cause ) throws Exception {Cause.printstacktrace ();} New data received @overridepublic void Messagereceived (iosession session, Object message) throws Exception {string msg = (string) m Essage; System.out.println ("messagereceived:" + msg); @Overridepublic void Sessioncreated (Iosession session) throws Exception {System.out.println ("sessioncreated");} @Overridepublic void Sessionclosed (Iosession session) throws Exception {System.out.println ("sessionclosed");}}
Netty:
Netty uses Lengthfieldbasedframedecoder to handle this kind of message. The new Lengthfieldbasedframedecoder (80, 0, 4, 0, 4) in the code below contains 5 parameters, namely int maxframelength, int lengthfieldoffset, int lengthfieldlength, int lengthadjustment, int initialbytestostrip. Maxframelength is the maximum length of the message, Lengthfieldoffset is the position of the header, Lengthfieldlength is the length of the header, Lengthadjustment is the length adjustment (the value in the default header indicates the length of the body and does not include the header itself), Initialbytestostrip to remove the bytes (the default decoding returns the entire contents of Header+body, This is set to 4 to remove the 4-byte header, leaving only the body).
public class TCPServer {public static void main (string[] args) throws Interruptedexception {Eventloopgroup Bossgroup = new Nioeventloopgroup (); Eventloopgroup Workergroup = new Nioeventloopgroup (); try {serverbootstrap b = new Serverbootstrap (); B.group (BossGroup, Workergroup). Channel (Nioserversocketchannel.class). Childhandler (New channelinitializer<socketchannel> () {@ overridepublic void Initchannel (Socketchannel ch) throws Exception {Channelpipeline pipeline = Ch.pipeline ();// Lengthfieldbasedframedecoder split messages by row, remove Bodypipeline.addlast (new Lengthfieldbasedframedecoder (80, 0, 4, 0, 4));// Then press UTF-8 encoding to turn to string pipeline.addlast (new Stringdecoder (charsetutil.utf_8));p ipeline.addlast (New Tcpserverhandler ());}); Channelfuture f = b.bind (8080). sync (); F.channel (). Closefuture (). sync (); finally {workergroup.shutdowngracefully (); bossgroup.shutdowngracefully ();}}} Class Tcpserverhandler extends Channelinboundhandleradapter {//Receive new data @overridepublic void Channelread ( Channelhandlercontext CTX, Object msg) {String message = (string) msg; System.out.println ("Channelread:" + message);} @Overridepublic void Channelactive (Channelhandlercontext ctx) {System.out.println ("channelactive");} @Overridepublic void Channelinactive (Channelhandlercontext ctx) {System.out.println ("channelinactive");} @Overridepublic void Exceptioncaught (Channelhandlercontext ctx, throwable cause) {cause.printstacktrace (); Ctx.close ( );}}
Twisted:
You need to inherit int32stringreceiver in twisted and no longer inherit protocol. The int32stringreceiver represents a fixed 32-bit (4-byte) header, plus int32stringreceiver, int8stringreceiver, and so on. The method of accepting data events that need to be implemented is no longer datareceived, nor linereceived, but stringreceived.
#-*-coding:utf-8–*-from twisted.protocols.basic import int32stringreceiverfrom twisted.internet.protocol Import Factoryfrom twisted.internet Import Reactorclass tcpserverhandle (int32stringreceiver): # New Connection Build def Connectionmade (self): print ' Connectionmade ' # Connection Disconnect def connectionlost (self, Reason): print ' Connectionlost ' # received new data def stringreceived (self, data): print ' stringreceived: ' + DataFactory = Factory ( ) Factory.protocol = tcpserverhandlereactor.listentcp (8080, Factory) Reactor.run ()
Here is a client-side test program written in Java:
public class TcpClient {public static void main (string[] args) throws IOException {socket socket = Null;dataoutputstream O UT = null;try {socket = new socket ("localhost", 8080); out = new DataOutputStream (Socket.getoutputstream ());//Request Server string data1 = "Newton"; byte[] outputBytes1 = data1.getbytes ("UTF-8"); Out.writeint (outputbytes1.length); Write Headerout.write (outputBytes1); Write bodystring data2 = "Einstein"; byte[] OutputBytes2 = data2.getbytes ("UTF-8"); Out.writeint (outputbytes2.length); Write Headerout.write (outputBytes2); Write Body} finally {//close connection out.close (); Socket.close ();}}}
Mina Server output results:
sessioncreated
Messagereceived: Newton
Messagereceived: Einstein
Sessionclosed
Netty Server Output results:
Channelactive
Channelread: Newton
Channelread: Einstein
Channelinactive
Twisted Server Output results:
Connectionmade
Stringreceived: Newton
Stringreceived: Einstein
Connectionlost
Fork Brother reproduced please indicate the source: http://blog.csdn.net/xiao__gui/article/details/38752105