Mina, Netty, twisted study Together (VI): Session

Source: Internet
Author: User

Students who have developed Web applications should always use the session. Because the HTTP protocol itself is stateless, a client accesses multiple pages of the Web application multiple times, and the server cannot tell if the client is the same client with multiple accesses. With the session, you can set some client-related properties to maintain this connection state. For example, when the user logs on to the system and the session flag is set, the client is logged on, so you don't have to log in again when you visit another page.

In synchronous blocking network programming, code is written in the order of TCP operations, which is to create a connection, read and write multiple times, close the connection, so it is easy to determine whether the sequence of operations is the same connection. In an event-driven asynchronous network programming framework, an IO operation triggers an event to invoke the corresponding event function, such as new data received from the client, called messagereceived (MINA), Channelread (Netty), DataReceived (Twisted), multiple requests for the same TCP connection and multiple client requests are the same.

So how to tell if multiple requests are not the same TCP connection, how to save connection related information? For this problem, MINA, Netty, twisted all provide the corresponding solution.

The following respectively implements a request count counter with Mina, Netty, and twisted to record the number of requests for the same connection multiple times.

MINA:

In Mina, whenever a client connects to the server, a new iosession is created until the client disconnects. Iosession can use setattribute and getattribute to store and retrieve information about a TCP connection.

public class TCPServer {public static void main (string[] args) throws IOException {Ioacceptor acceptor = new Niosocketacce Ptor (); Acceptor.getfilterchain (). AddLast ("Codec", new Protocolcodecfilter (New Textlinecodecfactory ( Charset.forname ("UTF-8"), "\ r \ n", "\ r \ n")), Acceptor.sethandler (New Tcpserverhandle ()); Acceptor.bind (new Inetsocketaddress (8080));}} Class Tcpserverhandle extends Iohandleradapter {@Overridepublic void Exceptioncaught (iosession session, Throwable cause ) throws Exception {Cause.printstacktrace ();} Receive new data @overridepublic void Messagereceived (iosession session, Object message) throws Exception {int counter = 1;//for the first time please Counterif (Session.getattribute ("counter") = = null) {Session.setattribute ("counter", 1);} else {// Get the counter in session, add 1 and then deposit Sessioncounter = (Integer) session.getattribute ("counter"); counter++; Session.setattribute ("Counter", counter);} String line = (string) message; System.out.println ("First" + Counter + "Request:" + line);}}

Netty:

There are two cases in Netty, one is to create a new Channelhandler instance for each TCP connection, and the other is to share a Channelhandler instance for all TCP connections. The difference between the two approaches is whether the new Channelhandler instance is added to the Channelpipeline AddLast method.

Create a new Channelhandler instance for each TCP connection:

Creating a new Channelhandler instance for each TCP connection is one of the most common ways. This is a very simple situation where you can save connection-related information by adding a member variable directly to the Channelhandler implementation class.

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 (); Pipeline.addlast (new Linebasedframedecoder);p ipeline.addlast (New Stringdecoder (Charsetutil.utf_8)); Pipeline.addlast (New Tcpserverhandler ()); Create a new Channelhandler instance for each TCP connection}}); Channelfuture f = b.bind (8080). sync (); F.channel (). Closefuture (). sync (); finally {workergroup.shutdowngracefully (); bossgroup.shutdowngracefully ();}}} Class Tcpserverhandler extends Channelinboundhandleradapter {//connection related information is stored directly in the member variable of the Tcpserverhandler private int counter = 0; @Overridepublic void Channelread (Channelhandlercontext ctx, OBJECT msg) {counter++; String line = (string) msg; System.out.println ("First" + Counter + "Request:" + line);} @Overridepublic void Exceptioncaught (Channelhandlercontext ctx, throwable cause) {cause.printstacktrace (); Ctx.close ( );}}

all TCP connections share a single Channelhandler instance:

In this case, the connection-related information cannot be placed in the member variables of the Channelhandler implementation class, otherwise the information will be shared by other connections. This is where the Channelhandlercontext attribute is going to be used.

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> () { Private Tcpserverhandler Tcpserverhandler = new Tcpserverhandler (), @Overridepublic void Initchannel (Socketchannel ch) Throws Exception {Channelpipeline pipeline = Ch.pipeline ();p ipeline.addlast (New Linebasedframedecoder (80)); Pipeline.addlast (New Stringdecoder (charsetutil.utf_8));p ipeline.addlast (Tcpserverhandler); Multiple connections using the same Channelhandler instance}}); Channelfuture f = b.bind (8080). sync (); F.channel (). Closefuture (). sync (); finally {workergroup.shutdowngracefully (); bossgroup.shutdowngracefully ();}}} @Sharable//Multiple connections using the same channelhandler, to add @sharable annotation class Tcpserverhandler extends Channelinboundhandleradapter { Private Attributekey<integer> Attributekey = attributekey.valueof ("counter"); @Overridepublic void Channelread ( Channelhandlercontext ctx, Object msg) {attribute<integer> Attribute = ctx.attr (attributekey); int counter = 1;IF ( Attribute.get () = = null) {Attribute.set (1);} else {counter = Attribute.get (); Counter++;attribute.set (counter);} String line = (string) msg; System.out.println ("First" + Counter + "Request:" + line);} @Overridepublic void Exceptioncaught (Channelhandlercontext ctx, throwable cause) {cause.printstacktrace (); Ctx.close ( );}}

Twisted:

In twisted, each TCP connection creates a new protocol instance, which is simple enough to save the connection-related information directly as a property of the Protocol inheriting class.

#-*-coding:utf-8–*-from twisted.protocols.basic import lineonlyreceiverfrom twisted.internet.protocol Import Factoryfrom twisted.internet Import Reactorclass tcpserverhandle (lineonlyreceiver):    def linereceived (self, data) :        if (hasattr (Self, ' counter ')):            Self.counter + = 1        else:            self.counter = 1;                    Print "First" + str (self.counter) + "Request:" + DataFactory = Factory () Factory.protocol = tcpserverhandlereactor.listentcp (8080, Factory) Reactor.run ()

The following is a Java-implemented client that has 3 TCP connections in the code and two request data to the server in each connection:

public class TcpClient {public static void main (string[] args) throws IOException, Interruptedexception {//3-times TCP connection, each connection sent 2 Request data for (int i = 0; i < 3; i++) {Socket socket = Null;outputstream out = null;try {socket = new socket ("localhost", 80 out = Socket.getoutputstream ();//First request server string lines1 = "hello\r\n"; byte[] outputBytes1 = lines1.getbytes ("UTF-8" ); Out.write (outputBytes1); Out.flush ();//second request server string lines2 = "world\r\n"; byte[] OutputBytes2 = Lines2.getbytes (" UTF-8 "); Out.write (outputBytes2); Out.flush ();} Finally {//close connection out.close (); Socket.close ();} Thread.Sleep (1000);}}

Test the above 4 servers separately, the output is:

1th Time Request: Hello
2nd Request: World
1th Time Request: Hello
2nd Request: World
1th Time Request: Hello
2nd Request: World


Fork Brother reproduced please indicate the source: http://blog.csdn.net/xiao__gui/article/details/39180209

Mina, Netty, twisted study Together (VI): Session

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.