Mina, Netty, and Twisted (6): session, nettytwisted

Source: Internet
Author: User

Mina, Netty, and Twisted (6): session, nettytwisted

All users who have developed Web applications should use the session. Because the HTTP protocol itself is stateless, the server cannot determine whether the client accessed for multiple times is the same as that of the web application. With session, you can set some client-related attributes to maintain this connection status. For example, after a user logs on to the system and sets the session to mark that the client has logged on, the user does not need to log on again when accessing other pages.

However, the content in this article is not the session of the Web application, but the session of the TCP connection. In fact, the two are quite different. The session Implementation Method of a Web application is not implemented based on the same TCP connection but through cookies. The session of the Web application is just to let everyone understand the concept of session.

In network programming of synchronous blocking, the code is written in the TCP operation order, that is, creating a connection, reading and writing multiple times, and closing the connection. This makes it easy to judge whether the operation is the same connection. In the event-driven Asynchronous Network programming framework, IO operations will trigger an event to call corresponding event functions. For example, when receiving new data from the client, messageReceived (MINA) will be called), channelRead (Netty), dataReceived (Twisted), multiple requests for the same TCP connection and multiple client requests are the same.

So how can we determine whether multiple requests are the same TCP connection and how to save connection-related information? To solve this problem, MINA, Netty, and Twisted provide corresponding solutions.

The following uses MINA, Netty, and Twisted to implement a request count counter, which is used to record the number of requests for multiple requests in the same connection.

MINA:

In MINA, each time a client connects to the server, a new IoSession is created until the client is disconnected. IoSession can use setAttribute and getAttribute to store and obtain information about a TCP connection.

Public class TcpServer {public static void main (String [] args) throws IOException {IoAcceptor acceptor = new NioSocketAcceptor (); 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 {@ Override public void exceptionCaught (IoSession session, Throwable cause) throws Exception {cause. printStackTrace ();} // receives new data @ Override public void messageReceived (IoSession session, Object message) throws Exception {int counter = 1; // The first request, create counter if (session. getAttribute ("counter") = null) {session. setAttribute ("counter", 1);} else {// obtain the counter in the session, add 1, and save it to the session counter = (Integer) session. getAttribute ("counter"); counter ++; session. setAttribute ("counter", counter);} String line = (String) message; System. out. println ("th" + counter + "Request:" + line );}}

Netty:

Netty can be divided into two situations: one is to create a new ChannelHandler instance for each TCP connection, and the other is that all TCP connections share a ChannelHandler instance. The difference between the two methods is that the ChannelPipeline addLast method adds a new ChannelHandler instance.

Create a new ChannelHandler instance for each TCP connection:

Creating a New ChannelHandler instance for each TCP connection is the most common method. This situation is very simple. You can directly add a member variable to the ChannelHandler implementation class to save connection-related information.

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> () {@ Override public void initChannel (SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch. pipeline (); pipeline. addLast (new LineBasedFrameDecoder (80); pipeline. 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 directly stored in the TcpServerHandler member variable private int counter = 0; @ Override public void channelRead (ChannelHandlerContext ctx, Object msg) {counter ++; String line = (String) msg; System. out. println ("Number" + counter + "Request:" + line) ;}@ Override public void exceptionCaught (ChannelHandlerContext ctx, Throwable cause) {cause. printStackTrace (); ctx. close ();}}

All TCP connections share one ChannelHandler instance:

In this case, connection-related information cannot be stored in the member variables of the ChannelHandler implementation class. Otherwise, the information will be shared by other connections. The Attribute of ChannelHandlerContext is used here.

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 (); @ Override public void initChannel (SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch. pipeline (); pipeline. addLast (new LineBasedFrameDecoder (80); pipeline. addLast (new StringDecoder (CharsetUtil. UTF_8); pipeline. addLast (tcpServerHandler); // use the same ChannelHandler instance for multiple connections}); ChannelFuture f = B. bind (8080 ). sync (); f. channel (). closeFuture (). sync ();} finally {workerGroup. shutdownGracefully (); bossGroup. shutdownGracefully () ;}}@ Sharable // multiple connections use the same ChannelHandler. The @ Sharable annotation class TcpServerHandler extends {private AttributeKey <Integer> attributeKey = AttributeKey. valueOf ("counter"); @ Override public 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 ("Number" + counter + "Request:" + line) ;}@ Override public void exceptionCaught (ChannelHandlerContext ctx, Throwable cause) {cause. printStackTrace (); ctx. close ();}}

Twisted:

In Twisted, a new Protocol instance is created for each TCP connection. This makes it easy to directly save connection-related information as a property of the Protocol inheritance 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 "th" + str (self. counter) + "requests:" + datafactory = Factory () factory. protocol = TcpServerHandlereactor. listenTCP (8080, factory) reactor. run ()

The following is a Java-implemented client. The code sends three TCP connections and sends two requests to the server in each connection:

Public class TcpClient {public static void main (String [] args) throws IOException, InterruptedException {// 3 TCP connections, each connection sends 2 request data for (int I = 0; I <3; I ++) {Socket socket = null; OutputStream out = null; try {socket = new Socket ("localhost", 8080); out = socket. getOutputStream (); // The 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 the connection out. close (); socket. close ();} Thread. sleep (1000 );}}}

Test the above four servers respectively. The output results are as follows:

1st requests: Hello
2nd requests: World
1st requests: Hello
2nd requests: World
1st requests: Hello
2nd requests: World


Who has spring integrated hibernate project, cannot use struts framework, if there is a servlet to provide data through mina or netty Communication

Sent to your mailbox


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.