Mina, Netty, Twisted learn Together (iii): TCP message fixed-size prefix (Header)

Source: Internet
Author: User
Tags throwable

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



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.