Java NiO Learning Three: NiO's non-blocking network communication

Source: Internet
Author: User

One, blocking and non-blocking

Traditional IO streams are blocked. That is, when a thread calls read () or write (), the thread is blocked until some data is read or written, and the thread cannot perform other tasks during this time. As a result, the server side must provide a separate thread for each client to handle when it completes the IO operation of network traffic, and when the server side needs to process a large number of clients, the performance drops dramatically.
Java NIO is non-blocking mode. When a thread reads and writes data from a channel, the thread can perform other tasks if no data is available. Threads typically use the idle time of non-blocking IO to perform IO operations on other channels, so separate threads can manage multiple input and output channels. Therefore, NIO allows the server to use one or a limited number of threads to process all clients connected to the server side at the same time.

Let me take a look at an example of using NIO to demonstrate a blocking style, i.e. without a selector:

Import Java.io.ioexception;import Java.net.inetsocketaddress;import Java.nio.bytebuffer;import Java.nio.channels.filechannel;import Java.nio.channels.serversocketchannel;import Java.nio.channels.socketchannel;import Java.nio.file.paths;import Java.nio.file.standardopenoption;import org.junit.test;/* * Three cores to complete network communication using NIO: * 1. Channel: Responsible for connection * * Java.nio.channels.Channel Interface: * |--selectablechannel * | -socketchannel * |--serversocketchannel * |--datagramchannel * * |--pipe. Sinkchannel * |--pipe.sourcechannel * * 2. Buffer: Responsible for data access * * 3. Selector (Selector): is a selectablechannel multiplexer. IO Status for monitoring Selectablechannel * */public class Testblockingnio {//client @Test public void client () throws Ioexce                ption{//1. Get channel Socketchannel SChannel = Socketchannel.open (New inetsocketaddress ("127.0.0.1", 9898)); FileChannel Inchannel = Filechannel.opeN (Paths.get ("1.jpg"), Standardopenoption.read); 2.                Allocates a buffer of the specified size Bytebuffer buf = bytebuffer.allocate (1024); 3.            Reads the local file and sends it to the service side while (Inchannel.read (BUF)! =-1) {buf.flip ();            Schannel.write (BUF);        Buf.clear (); }//4.        Close channel Inchannel.close ();    Schannel.close (); }//service-side @Test public void server () throws ioexception{//1. Get channel Serversocketchannel Sschannel                = Serversocketchannel.open ();                FileChannel Outchannel = Filechannel.open (Paths.get ("2.jpg"), Standardopenoption.write, standardopenoption.create); 2.                Bind connection Sschannel.bind (new Inetsocketaddress (9898)); 3.                Gets the channel of the client connection Socketchannel SChannel = Sschannel.accept (); 4.                Allocates a buffer of the specified size Bytebuffer buf = bytebuffer.allocate (1024); 5.    Receives the client's data and saves it to local while (Schannel.read (BUF)! =-1) {buf.flip ();        Outchannel.write (BUF);        Buf.clear (); }//6.        Close channel Schannel.close ();        Outchannel.close ();            Sschannel.close (); }    }

So to solve the above method, when there is no selector before, for the blocking situation, we can use the following method: (send complete, automatically shut down to notify the completion of the sent)

Import Java.io.ioexception;import Java.net.inetsocketaddress;import Java.nio.bytebuffer;import Java.nio.channels.filechannel;import Java.nio.channels.serversocketchannel;import Java.nio.channels.socketchannel;import Java.nio.file.paths;import Java.nio.file.standardopenoption;import Org.junit.test;public class TestBlockingNIO2 {//client @Test public void client () throws ioexception{so                Cketchannel SChannel = Socketchannel.open (New inetsocketaddress ("127.0.0.1", 9898));                FileChannel Inchannel = Filechannel.open (Paths.get ("1.jpg"), Standardopenoption.read);                Bytebuffer buf = bytebuffer.allocate (1024);            while (Inchannel.read (BUF)! =-1) {buf.flip ();            Schannel.write (BUF);        Buf.clear (); } Schannel.shutdownoutput (); Receive service side feedback int len = 0;            while (len = Schannel.read (BUF))! =-1) {buf.flip ();            System.out.println (New String (Buf.array (), 0, Len));        Buf.clear ();        } inchannel.close ();    Schannel.close (); }//service-side @Test public void server () throws ioexception{serversocketchannel Sschannel = Serversocketcha                Nnel.open ();                FileChannel Outchannel = Filechannel.open (Paths.get ("2.jpg"), Standardopenoption.write, standardopenoption.create);                Sschannel.bind (New Inetsocketaddress (9898));                Socketchannel SChannel = sschannel.accept ();                Bytebuffer buf = bytebuffer.allocate (1024);            while (Schannel.read (BUF)! =-1) {buf.flip ();            Outchannel.write (BUF);        Buf.clear ();        }//Send feedback to client buf.put ("Server received data successfully". GetBytes ());        Buf.flip ();                Schannel.write (BUF);        Schannel.close (); OutChannel.close ();    Sschannel.close (); }}

Second, selector (Selector)

The selector (Selector) is a multiplexer for the Selectablechannle object, and Selector can monitor the IO status of multiple selectablechannel at the same time, that is, using Selector enables a single thread to manage multiple Cha Nnel. Selector is the core of non-blocking IO.
The structure of Selectablechannle is as follows:

The application of the selector (Selector)

Create Selector : Create a Selector by calling the Selector.open () method .

Register Channel to selector: selectablechannel.register (Selector sel, int ops)

Selector ( Selector) Applications

When you call register (Selector sel, int ops) to register the channel with the selector, the selector listens to the channel for events that need to be specified by the second parameter ops.
Types of events that can be monitored (four constants using Selectionkey):
? READ: Selectionkey.op_read (1)
? Write: Selectionkey.op_write (4)
? Connection: Selectionkey.op_connect (8)
? Receiving: Selectionkey.op_accept (16)
If you are registering more than one event, you can use the bitwise OR operator to connect

Cases:

Selectionkey

Selectionkey: Represents the registration relationship between Selectablechannel and Selector. An event (select key) is selected each time a channel is registered with the selector. The selection key contains two sets of operations represented as integer values. Each bit of the action set represents a class of selectable operations supported by the channel of the key.

Method Description
int Interestops () Get collection of events of interest
int Readyops () Gets the collection of operations that the channel is already ready for
Selectablechannel Channel () Get registration Channel
Selector Selector () Return Selector
Boolean isreadable () Detects if read events are ready in channal
Boolean iswritable () Detects if write events are ready in channal
Boolean isconnectable () Detects if the connection is ready in the Channel
Boolean isacceptable () Detects if reception is ready in the Channel

Selector Common methods of

Method Description
set<selectionkey> keys () All the Selectionkey collections. On behalf of the channel registered on the selector
Selectedkeys () The selected Selectionkey collection. Returns the selected key set for this selector
int Select () Monitor all registered channel, and when they have IO operations that need to be processed,
The method returns, and will add the selected Selectionkey to the due
In the Selectionkey collection, the method returns the number of these Channel numbers.
int Select (Long timeout) You can set the time-out select () operation
int Selectnow () Executes a select () operation that returns immediately, which does not block the thread
Selector Wakeup () Causes a Select () method that has not yet returned to return immediately
void Close () Close the Selector

Socketchannel

The Socketchannel in Java NiO is a channel that connects to a TCP network socket.
Operation Steps:
? Open Socketchannel
? Read and write Data
? Close Socketchannel

The Serversocketchannel in Java NiO is a channel that can listen for incoming TCP connections, just like serversocket in standard IO
code sample;

Package Com.atguigu.nio;import Java.io.ioexception;import Java.net.inetsocketaddress;import java.nio.ByteBuffer; Import Java.nio.channels.selectionkey;import Java.nio.channels.selector;import Java.nio.channels.serversocketchannel;import Java.nio.channels.socketchannel;import Java.util.Date;import Java.util.iterator;import Java.util.scanner;import org.junit.test;/* * I. Three cores for network communication using NIO: * * 1. Channel: Responsible for connection * * Java.nio.channels.Channel Interface: * |--selectablechannel * | -socketchannel * |--serversocketchannel * |--datagramchannel * * |--pipe. Sinkchannel * |--pipe.sourcechannel * * 2. Buffer: Responsible for data access * * 3. Selector (Selector): is a selectablechannel multiplexer.  IO Status for monitoring Selectablechannel * */public class Testnonblockingnio {//client @Test public void client () throws ioexception{//1. Get channel Socketchannel SChannel = Socketchannel.open (New inetsocketaddress ("127.0.0.1 ", 9898)); 2.                Toggle non-blocking mode schannel.configureblocking (false); 3.                Allocates a buffer of the specified size Bytebuffer buf = bytebuffer.allocate (1024); 4.                Send data to the server Scanner scan = new Scanner (system.in);            while (Scan.hasnext ()) {String str = scan.next ();            Buf.put (New Date (). toString () + "\ n" + str). GetBytes ());            Buf.flip ();            Schannel.write (BUF);        Buf.clear (); }//5.    Close channel Schannel.close (); }//service-side @Test public void server () throws ioexception{//1. Get channel Serversocketchannel Sschannel = Se                Rversocketchannel.open (); 2.                Toggle non-blocking mode sschannel.configureblocking (false); 3.                Bind connection Sschannel.bind (new Inetsocketaddress (9898)); 4.                Get selector Selector Selector = Selector.open (); 5. Registers the channel with the selector and specifies "Listen for receive events" Sschannel.register (selector, selectionkey.op_accept); 6.            Polling gets the event "ready" on the selector while (Selector.select () > 0) {//7. Gets all registered "Select keys (Listening events ready)" in the current selector                        Iterator<selectionkey> it = Selector.selectedkeys (). Iterator ();                                while (It.hasnext ()) {//8. Get ready for "ready" is the event Selectionkey SK = It.next (); 9. Determine what the specific event is ready if (sk.isacceptable ()) {//10. Get client connections if "ready to receive" Socketchan                                        Nel sChannel = sschannel.accept (); 11.                                        Toggle non-blocking mode schannel.configureblocking (false); 12.                Register the channel on the selector schannel.register (selector, selectionkey.op_read); }else if (sk.isreadable ()) {//13. Gets the channel of the "Read Ready" state on the current selector socketchannel SChannel = (Socket                                        Channel) Sk.channel (); 14. Read Data BYtebuffer buf = bytebuffer.allocate (1024);                    int len = 0;                        while (len = Schannel.read (buf)) > 0) {buf.flip ();                        System.out.println (New String (Buf.array (), 0, Len));                    Buf.clear (); }}//15.            Deselect key Selectionkey It.remove (); }        }    }}

Datagramchannel

The Datagramchannel in Java NiO is a channel that can send and receive UDP packets.
? Operation Steps:
? Open Datagramchannel
? Receive/Send data

examples;

Package Com.atguigu.nio;import Java.io.ioexception;import Java.net.inetsocketaddress;import java.nio.ByteBuffer; Import Java.nio.channels.datagramchannel;import Java.nio.channels.selectionkey;import java.nio.channels.Selector; Import Java.util.date;import java.util.iterator;import Java.util.scanner;import Org.junit.test;public class TestNonBlockingNIO2 {@Test public void Send () throws ioexception{datagramchannel dc = DATAGRAMCHANNEL.O                Pen ();                Dc.configureblocking (FALSE);                Bytebuffer buf = bytebuffer.allocate (1024);                Scanner scan = new Scanner (system.in);            while (Scan.hasnext ()) {String str = scan.next ();            Buf.put (New Date (). toString () + ": \ n" + str). GetBytes ());            Buf.flip ();            Dc.send (buf, New inetsocketaddress ("127.0.0.1", 9898));        Buf.clear ();    } dc.close (); } @Test public void receive () throws ioexception{DatagramchannelDC = Datagramchannel.open ();                Dc.configureblocking (FALSE);                Dc.bind (New Inetsocketaddress (9898));                Selector Selector = Selector.open ();                Dc.register (selector, selectionkey.op_read);                        while (Selector.select () > 0) {iterator<selectionkey> it = Selector.selectedkeys (). Iterator ();                                while (It.hasnext ()) {Selectionkey SK = It.next ();                                        if (sk.isreadable ()) {Bytebuffer buf = bytebuffer.allocate (1024);                    Dc.receive (BUF);                    Buf.flip ();                    System.out.println (New String (Buf.array (), 0, Buf.limit ()));                Buf.clear ();        }} it.remove (); }    }}

Piping (Pipe)

The Java NIO pipeline is a one-way data connection between 2 threads. The pipe has a source channel and a sink channel. The data is written to the sink channel, which is read from the source channel.

Write data to the pipeline

Reading data from a pipeline

Data from the Read pipeline requires access to the source channel.

Call the Read () method of the source channel to read the data

Code Sample:

Import Java.io.ioexception;import java.nio.bytebuffer;import Java.nio.channels.pipe;import org.junit.Test;public Class Testpipe {    @Test public    void Test1 () throws ioexception{        //1. Get piping Pipe pipe        = Pipe.open ();                2. Writes the data in the buffer to the pipe        bytebuffer buf = bytebuffer.allocate (1024x768);                Pipe.sinkchannel Sinkchannel = Pipe.sink ();        Buf.put ("Send data through a one-way pipe". GetBytes ());        Buf.flip ();        Sinkchannel.write (BUF);                3. Reads the data in the buffer        pipe.sourcechannel Sourcechannel = Pipe.source ();        Buf.flip ();        int len = Sourcechannel.read (BUF);        System.out.println (New String (Buf.array (), 0, Len));                Sourcechannel.close ();        Sinkchannel.close ();    }    }

Java NiO Learning Three: NiO's non-blocking network communication

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.