Netty realization of NIO in actual combat __nio

Source: Internet
Author: User
Tags readline
Netty Introduction

Netty is a Java open source framework provided by JBoss. Netty provides asynchronous, event-driven network application frameworks and tools for rapid development of high-performance, highly reliable network servers and client programs.
In other words, Netty is a customer, server-side programming framework based on NIO, which simplifies and streamlines the programming development of network applications, such as the development of socket services for TCP and UDP.
Netty absorbs a variety of protocols (including FTP, SMTP, HTTP, a variety of binary, text protocol) Implementation experience, while ensuring easy development while also ensuring its application performance, stability and scalability. Netty Use Example

Service-side code

public class Timeserver {public static void main (string[] args) throws Exception {new Timeserver (). BIND (808
    6); public void bind (int port) throws Exception {//config server-side NIO thread Group Eventloopgroup bossgroup=new Nioeventl
        Oopgroup ();

      Eventloopgroup Workergroup = new Nioeventloopgroup ();
          try{serverbootstrap b=new serverbootstrap (); B.group (Bossgroup,workergroup). Channel (nioserversocketchannel.class). Option (Channelo Ption.

          so_backlog,1024). Childhandler (New Childchannelhandler ());

          Bind port, synchronization waits for Success Channelfuture F=b.bind (port). sync ();
      Wait for the service-side listening port to close F.channel (). Closefuture (). sync ();
              }finally {//Free thread pool resource bossgroup.shutdowngracefully ();
          Workergroup.shutdowngracefully (); }} Private class Childchannelhandler extends Channelinitializer<socketchannel>{@Override protected void Initchannel (Socketchannel channel) throws Exception {//Channe
            L.pipeline (). AddLast (New Delimiterbasedframedecoder (1024, unpooled.copiedbuffer ("\ n". GetBytes ()));
            Channel.pipeline (). AddLast (New Fixedlengthframedecoder (17));
           Channel.pipeline (). AddLast (New Stringdecoder ());
            Channel.pipeline (). AddLast (New Timeserverhandler ()); Channel.pipeline (). AddLast (New Channelhandleradapter () {@Override public void Channelread (
                    Channelhandlercontext ctx, Object msg) throws Exception {System.out.println (msg);
                    Byte[] result= ("Server:" +msg+system.getproperty ("Line.separator")). GetBytes ();
                    Bytebuf buf= Unpooled.copiedbuffer (result);
                Ctx.writeandflush (BUF); @Override public void Channelreadcomplete (Channelhandlercontext ctx) throws ExceptIon {Ctx.flush (); @Override public void Exceptioncaught (Channelhandlercontext ctx, throwable cause) throw
                    S Exception {cause.printstacktrace ();
                Ctx.close ();
        }
            }); }
    }
}

Client code

public class Timeclient {public static void main (string[] args) throws interruptedexception {new timeclient
    (). Connect (8086, "127.0.0.1"); public void Connect (int port,string host) throws Interruptedexception {//Configure client NIO thread Group Eventloopgrou
        P group=new Nioeventloopgroup ();
            try{Bootstrap b=new Bootstrap ();
                    B.group (Group). Channel (niosocketchannel.class). Option (Channeloption.tcp_nodelay,true) . Handler (new channelinitializer<socketchannel> () {@Override PR otected void Initchannel (Socketchannel channel) throws Exception {Channel.pipeline (). AddLast (
                            New Delimiterbasedframedecoder (1024, unpooled.copiedbuffer ("\ n". GetBytes ()));
                            Channel.pipeline (). AddLast (New Stringdecoder ());
                 Channel.pipeline (). AddLast (New Channelhandleradapter () {               @Override public void channelactive (Channelhandlercontext ctx) throws Excep
                                    tion {System.out.println ("enter");
                                    BufferedReader br=new BufferedReader (New InputStreamReader (system.in));
                                    String Line=br.readline ();
                                    System.out.println ("Enter1:" +line); while (!) EOF ". Equals (line)) {byte[] bytes= (Line+system.getproperty (" Line.separator ")). Getby
                                        TES ();
                                        Bytebuf Buf=unpooled.buffer (bytes.length);
                                        Buf.writebytes (bytes);
                                        Ctx.writeandflush (BUF);
                                        Line=br.readline ();
                                    System.out.println ("Enter1:" +line);    }
//                                Byte[] bytes= ("QUERY Time Order" +system.getproperty ("Line.separator")). GetBytes ();
Bytebuf Buf=unpooled.buffer (bytes.length);
Buf.writebytes (bytes);
                                Ctx.writeandflush (BUF);  @Override public void Channelread (Channelhandlercontext
                                Ctx,object msg) throws Exception {System.out.println (msg);
                        }
                            });

            }
                    });

            Initiates an asynchronous connection Operation Channelfuture F=b.connect (host,port). sync ();
        Wait for the client link to close F.channel (). Closefuture (). sync ();
        }finally {//release of NIO thread Group group.shutdowngracefully (); }
    }
}

What the client does is to read the user's input and then send it to the server, because Fixedlengthframedecoder this handler, it must be 17 characters to send success.
As you can see from the example, what we can do and need to do is customize the content processor. It's like a service, like the Tomcat service, where we can't change the container itself, and all we can do is provide a different response on request.
There are also a number of fixed codes in the example, which are configuration items for the service, like Tomcat, and we can change its behavior and performance through different configurations.

See here, you may still be ignorant, do not know what Netty for us to do, now we look at the direct use of NIO code.
Service-Side code:

public class Nioserver {private int flag = 0;

    Read-write buffer size private int block=4096;

    Send buffer private Bytebuffer Sendbuffer = bytebuffer.allocate (block);

    Receive buffer private Bytebuffer Receivebuffer = bytebuffer.allocate (block);

    Private Selector Selector; public nioserver (int port) throws IOException {Serversocketchannel serversocketchannel= serversocketchannel.open ()
        ;

        Serversocketchannel.configureblocking (FALSE);
        ServerSocket Serversocket=serversocketchannel.socket ();

        Serversocket.bind (New Inetsocketaddress (port));
        Selector=selector.open ();
        Serversocketchannel.register (selector, selectionkey.op_accept);
    SYSTEM.OUT.PRINTLN ("Server Start---" +port); 
            /** * Monitor * @throws IOException/private void Listen () throws ioexception{while (true) {

            Selector.select ();
            set<selectionkey> Selectionkeys = Selector.selectedkeys (); IteratOr<selectionkey> Itr=selectionkeys.iterator ();
                while (Itr.hasnext ()) {Selectionkey selectionkey=itr.next ();
                Itr.remove (); Handlekey (Selectionkey);//Processing Selectionkey}}}/** * processing Selectionkey, read/write * @param s
        Electionkey * @throws IOException * * private void Handlekey (Selectionkey selectionkey) throws ioexception{
        Socketchannel Client=null;

            if (selectionkey.isacceptable ()) {Serversocketchannel server= (Serversocketchannel) Selectionkey.channel ();
            Client=server.accept ();
            Client.configureblocking (FALSE);
        Client.register (Selector,selectionkey.op_read);

            }else if (selectionkey.isreadable ()) {client= (Socketchannel) Selectionkey.channel ();
            Receivebuffer.clear ();
            int Count=client.read (receivebuffer); if (count>0) {string Receivetext=new string (receivEbuffer.array (), 0,count);

                SYSTEM.OUT.PRINTLN ("server-side receiving client data-:" +receivetext);
            Client.register (Selector,selectionkey.op_write)//Register write operation}}else if (Selectionkey.iswritable ()) {

            Client= (Socketchannel) Selectionkey.channel ();
            String sendtext= "message from server--" +flag++;
            Sendbuffer.clear ();
            Sendbuffer.put (Sendtext.getbytes ());
            Sendbuffer.flip ();
            Client.write (Sendbuffer);

            SYSTEM.OUT.PRINTLN ("The server sends the data to the client--" +sendtext); Client.register (Selector,selectionkey.op_read);
        Register read Operations}} public static void Main (string[] args) throws ioexception{int port = 8888;
        Nioserver server=new Nioserver (port);
    Server.listen (); }
}

Client code:

public class Nioclient {private int block = 4096;

    Private Bytebuffer sendbuffer=bytebuffer.allocate (block);

    Private Bytebuffer receivebuffer=bytebuffer.allocate (block);

    Private Selector Selector;
        Public Nioclient (String host,int port) throws ioexception{Socketchannel Channel=socketchannel.open ();

        Channel.configureblocking (FALSE);
        Selector=selector.open ();
        Channel.register (selector, selectionkey.op_connect);
    Channel.connect (New Inetsocketaddress (host, port)); /** * Connect the server and make the request * @throws IOException/public void Connect () throws ioexception{Whil
            E (True) {selector.select ();
            Handlekey (Selector.selectedkeys ());
        Selector.selectedkeys (). Clear (); }/** * Handles Select to key * @param selectionkeys * @throws ioexception * * * public void ha Ndlekey (set<selectionkey> Selectionkeys) throws IOException {IterAtor<selectionkey> Itr=selectionkeys.iterator ();
            while (Itr.hasnext ()) {Selectionkey selectionkey=itr.next ();

            Socketchannel client= (Socketchannel) Selectionkey.channel ();
                if (selectionkey.isconnectable ()) {System.out.println ("client Connect");
                    if (client.isconnectionpending ()) {client.finishconnect ();

                    SYSTEM.OUT.PRINTLN ("Complete connection!");
                    First write Data sendbuffer.clear ();
                    Sendbuffer.put ("Hello,server". GetBytes ());
                    Sendbuffer.flip ();
                Client.write (Sendbuffer);
            } client.register (Selector,selectionkey.op_read);

                }else if (selectionkey.isreadable ()) {receivebuffer.clear ();
                reading data int count=client.read (receivebuffer); if (count>0) {string Receivetext=new string (reCeivebuffer.array (), 0,count);
                    SYSTEM.OUT.PRINTLN ("Client accepts server-side data-:" +receivetext);
                Client.register (Selector,selectionkey.op_write);
    }} selectionkeys.clear ();
            public void Write (String content) throws IOException {Out:while (true) {selector.select ();
            Set<selectionkey> Selectionkeys=selector.selectedkeys ();
            Iterator<selectionkey> Itr=selectionkeys.iterator ();
                while (Itr.hasnext ()) {Selectionkey selectionkey=itr.next ();
                    if (selectionkey.iswritable ()) {itr.remove ();
                    Bytebuffer sendbuffer=bytebuffer.allocate (block);
                    Sendbuffer.put (Content.getbytes ());
                    Sendbuffer.flip ();
                    Socketchannel client= (Socketchannel) Selectionkey.channel ();
        Reset the buffer of each flag bit, because put the data to the inside, the logo is changed, want to read from the data sent to the service side, we need to reset            Sendbuffer.flip ();
                    Client.write (Sendbuffer);

                    SYSTEM.OUT.PRINTLN ("The client sends data to the server--:" +content);
                Break out; }}} public static void Main (string[] args) throws IOException {final Nioclient C
        Lient=new nioclient ("127.0.0.1", 8888);
                New Thread (New Runnable () {public void run () {try {client.connect ();
                catch (IOException e) {e.printstacktrace ();
        }}). Start ();
        Client.write ("Test1testtest");
        try {thread.sleep (100000l);
        catch (Interruptedexception e) {e.printstacktrace ();
        } System.out.println ("DD");

    Client.write ("Test2testtest"); }
}

Compared to the above code, the direct use of NIO is a lot more detail, many of the code directly interacting with IO, such as connection events, read events, write events, as well as read and write models, coding process design, which also need to deal with themselves.
See here, you should understand, Netty is a layer of NIO encapsulation, provides a set of templates, we can get through the configuration of different threading model, weighing the throughput, responsiveness and other indicators. Reactor Threading Model

Three models with single thread, multi-threading, master-slave reactor
Netty can use these three models flexibly through configuration, and a third model is recommended for high concurrency and high load.

Small knitting began also very puzzled why to have a subreactor, but please look carefully, the master-slave reactor model of the acceptor is one-way, and the ordinary reactor model is two-way , This means that the master and subordinate reactor Mainreactor only do receive requests and distribution of things, received after the things are thrown to the subreactor processing. For example, when listening to multiple ports, each subreactor listens on one port. Netty Framework Implementation (single reactor multiple threads, long connection version)

Let's talk about the implementation of the Netty framework, mainly for the main reactor multithreading model as an example.
The process is as follows:

The following code is attached, which is an example of a long connection that the server and the client can freely read and write at any time (the main part):

Common Template classes:

/** * NIO Operations template class * Server and client base class * Created by Guzy on 16/9/18.

    * * Public abstract class Niotemplate {Logger Logger=logger.getlogger (niotemplate.class);


    protected Selector Selector; /** * Main Channel * * Selectablechannel channel; TODO: Consider taking off/** * content processing chain/private list<contenthandler> contenthandlers=new Arraylist<conte

    Nthandler> ();

    /** * Whether it is necessary to continue to run * * protected volatile Boolean running=true;

    /** * Display name/String name;


    Worker threads, used to process data content private Executorservice executorservice;
        Public niotemplate (String name) {this.name=name;
    Executorservice= Executors.newfixedthreadpool (10);
        Public niotemplate Addcontenthandler (ContentHandler contenthandler) {contenthandlers.add (ContentHandler);
    return this; /** * Client Registration (Login) event handling * @param selectionkey * @param results/abstract void HANDLEFIRSTC OnneCT (selectionkey selectionkey,list<object> results);

    /** * Handle Shutdown Event * @param selectionkey/abstract void Handleclose (Selectionkey selectionkey);

    /** * Write down the data to be written * * abstract void Handlenotwritten ();

    abstract void ShutDown ();

    abstract void Handlekey (Selectionkey selectionkey) throws IOException;
        /** * Start method * @throws IOException/public void start () {if (!running) {return; } try{while (running) {//registerselectionkey ();//Register Write interest Handlenot

                Written ();
                int Count=selector.select ();

                    if (count>0) {final set<selectionkey> selectionkeys= selector.selectedkeys ();
                    For (final Selectionkey Selectionkey:selectionkeys) {handlekey (Selectionkey);
                } selectionkeys.clear ();
   }
            }     }catch (Exception e) {e.printstacktrace ();
        }finally {shutDown ();  /** * Read Event processing * @param selectionkey * @throws ioexception/void handlereadable (final Selectionkey Selectionkey) throws IOException {//todo: expansion, concurrent final bytebuffer Receivebuffer = Selectionke Y.attachment () ==null?

        Bytebuffer.allocate (1024):(Bytebuffer) selectionkey.attachment ();
        Final Socketchannel channel = (Socketchannel) selectionkey.channel ();
        Reads the data int count = Channel.read (Receivebuffer);
                    if (Count > 0) {executorservice.execute (new Runnable () {public void run () {

                    Receivebuffer.flip ();
                    list<object> results = new arraylist<object> ();
                    Results.add (Receivebuffer); for (ContentHandler handler:contenthandlers) {list<object> outs = new ArrayList<object> ();
                        Iterator Resultitr = Results.iterator ();
                            while (Resultitr.hasnext ()) {Object Curresult = Resultitr.next ();
                        Handler.read (channel, Curresult, outs);
                    } results = outs;

                    } handlefirstconnect (Selectionkey,results);
                    for (Object curresult:results) {logger.debug (name + "Receive data:" + new String (byte[)) curresult);

            }
                }
            }); Channel.register (Selector, Selectionkey.op_write | Selectionkey.op_read);
            TODO: You may want to change it here to register the write event} else if (Count < 0) {//on end link off selectionkey.cancel ();
            Channel.close ();
        Handleclose (Selectionkey); else {//read to 0 bytes, ignore}}/** * Write content * @param channel * @parAM content * @throws ioexception/void Writecontent (final bytebuffer attach,final Socketchannel Channel,fi NAL Object content) {Executorservice.submit (new callable<list<object>> () {List<object

            > results = new arraylist<object> ();
                Public list<object> Call () throws IOException {Results.add (content);

                Logger.debug (name + "Send:" + content); for (ContentHandler handler:contenthandlers) {list<object> outs = new arraylist<object>
                    ();
                    for (Object result:results) {handler.write (Attach,channel, result, outs);
                } results = outs;
                The IF (attach!=null) {//is written directly to the attach in the Writecontent (Channel,attach); }else{for (Object result:results) {writecontent(channel, (bytebuffer) result);

            } return results;

    }
        }); /** * Underlying write content method * @param socketchannel * @param sendbuffer *

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.