In the previous blog post, there is a way to introduce the wrapping of cut messages.
But there is a small problem, such a method, the message itself includes a newline character, that will be cut into two of the message. The result is not correct.
This article describes the second method of message cutting, which is 2nd in the previous blog post: Use a fixed length header that indicates the length of the body. The message is cut by specifying the number of bytes in the body with a header prefix of a fixed number of bytes.
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. This integer 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 such a message to the relevance and decoding.
MINA:
Mina provides a prefixedstringcodecfactory to encode messages of this type for decoding. Prefixedstringcodecfactory The default header size is 4 bytes. Of course it can be specified as 1 or 2.
public class TCPServer {public static void main (string[] args) throws IOException {Ioacceptor acceptor = new Niosocketacce Ptor ();//The 4-byte header specifies the number of bytes in the body. The handling 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 such messages.
The new Lengthfieldbasedframedecoder (80, 0, 4, 0, 4) in the following code includes 5 parameters, each of which is int maxframelength, int lengthfieldoffset, int lengthfieldlength, int lengthadjustment, int initialbytestostrip. Maxframelength is the maximum length of the message. Lengthfieldoffset is the location 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.) Does not include the header itself), Initialbytestostrip is the number of bytes removed (the default decoding of all content returned 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 cut messages by line, 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:
In twisted, you need to inherit int32stringreceiver, and no longer inherit protocol.
The int32stringreceiver represents a fixed 32-bit (4-byte) header, plus int16stringreceiver, 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 ()
The following is a client 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 SERVERSTR ing 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 Bodyout.flush ();} Finally {//close connection out.close (); Socket.close ();}}}
Minaserver Output Results:
sessioncreated
Messagereceived: Newton
Messagereceived: Einstein
Sessionclosed
Nettyserver 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
Copyright notice: This article Bo Master original articles, blogs, without consent may not be reproduced.
Mina, Netty, Twisted learn Together (iii): TCP prefix fixed-size message (Header)