The Java-NIO Selector and Pipe

About blocking and non-blocking: https://www.cnblogs.com/jhxxb/p/11272727.html

 

First, the traditional IO streams are blocking the

When a thread calls read () or write (), the thread is blocked until there is some data to be read or written to, the thread in the meantime can not perform other tasks.

Therefore, when the communication network IO operation, because the thread is blocked, so the server must have a separate thread for processing for each client, when the server needs to handle large number of clients, a sharp decline in performance.

package nio;

import org.junit.Test;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Scanner;


public class TestBlockingNIO {

    // 客户端
    @Test
    public void client() throws IOException {
        // 获取通道
        SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898)); 

        // allocate a buffer size specified 
        the ByteBuffer buf = ByteBuffer.allocate (1024 ); 

        // sent to the server 
        Scanner Scan = new new Scanner (the System.in);
         the while (scan.hasNext ()) { 
            String STR = scan.next (); 
            buf.put (str.getBytes ()); 
            buf.flip (); 
            sChannel.write (buf); 
            buf.clear (); 

            IF ( "Exit" .equals (STR)) {
                 BREAK ; 
            } 
        } 


        // receiving feedback service side 
        sChannel.shutdownOutput ();
         int len = 0;
         The while (! (Len = sChannel.read (buf)) = -1 ) { 
            buf.flip (); 
            System.out.println ( new new String (buf.array (), 0 , len)); 
            buf.clear ( ); 
        } 

        // close the passage 
        sChannel.close (); 
    } 

    // server 
    @Test
     public  void Server () throws IOException {
         // acquisition channel 
        a ServerSocketChannel ssChannel = ServerSocketChannel.open (); 

        // bound connection 
        ssChannel.bind ( new new the InetSocketAddress (9898 ));

        the retry: 
        the while ( to true ) {
             // acquisition channel client connection 
            the SocketChannel Schannel = ssChannel.accept (); 

            // allocate a buffer size specified 
            the ByteBuffer buf = ByteBuffer.allocate (1024 ); 

            // receiving the client's data 
            the while ( ! sChannel.read (buf) = -1 ) { 
                String STR = new new String (buf.array ()) TRIM. ();
                 IF ( "Exit" .equals (STR)) {
                     BREAK the retry; 
                } 
                buf.flip () ;  
                System.out.println (STR);
                buf.clear (); 
            }

             // send back to the client 
            buf.put ( "the server successfully receives the data!" .getBytes ()); 
            buf.flip (); 
            sChannel.write (buf); 

            // Close Channel 
            sChannel .close (); 
        } 

        // close the passage 
        ssChannel.close (); 
    } 
}
View Code

 

Two, Java NIO is non-blocking

When the thread to read and write data from a channel, if no data is available, the thread can perform other tasks.

The threads are usually non-blocking IO idle time for performing IO operations on other channels, so a separate thread to manage a plurality of input and output channels.

Therefore, NIO allows the server to use one or a limited number of threads to simultaneously handle all client connections to the server.

Note: IO NIO or synchronous behavior.

/ * 
 * NIO completed using three core communication network: 
 * 
 * 1. channels (Channel): responsible for connecting 
 * java.nio.channels.Channel Interface: 
 * | --SelectableChannel 
 * | --SocketChannel 
 * | --ServerSocketChannel 
 * | --DatagramChannel 
 * 
 * | --Pipe.SinkChannel 
 * | --Pipe.SourceChannel 
 * 
 * 2. buffer (buffer): responsible for data access 
 * 
 * 3. selector (selector): is a multiplexed SelectableChannel Appliances. IO is used to monitor the status of SelectableChannel 
 * can listen to the type of event (using four constants SelectionKey representation) 
 * Reading: SelectionKey.OP_READ (1) 
 * wrote: SelectionKey.OP_WRITE (4) 
 * connection: SelectionKey.OP_CONNECT (8) 
 * reception: SelectionKey.OP_ACCEPT (16)
 * 
 * Selector conventional method 
 * Set <SelectionKey> keys () : set all SelectionKey. Registered on behalf of the Selector Channel 
 * selectedKeys (): selected SelectionKey collection. Returns the selected key set Selector 
 * intselect (): monitoring all registered Channel, when the intermediate IO operations they have to be processed, the method returns, and the corresponding SelectionKey was added SelectionKey set is selected, the method returns the number of these Channel. 
 * Int select (long timeout): You can set a long timeout select () operation 
 * int selectNow (): Returns the immediate implementation of a select () operation, which does not block the thread 
 * Selector wakeup (): make a return yet the select () method returns immediately 
 * void close (): close the selector 
 * /

1.TCP-SocketChannel

package nio;

import org.junit.Test;

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;

public class TestNonBlockingNIO {

    //客户端
    @Test
    public void client() throws IOException {
         // acquisition channel 
        the SocketChannel the SocketChannel.open Schannel = ( new new the InetSocketAddress ( "127.0.0.1", 9898 )); 

        // switch nonblocking 
        sChannel.configureBlocking ( to false ); 

        // allocate the specified buffer size 
        ByteBuffer buf ByteBuffer.allocate = (1024 ); 

        // send data to the server 
        Scanner Scan = new new Scanner (the System.in); 

        the while (scan.hasNext ()) { 
            String STR = scan.next (); 
            buf.put (( new new . DATE () toString () + "\ n-" + STR) .getBytes ());
            buf.flip (); 
            sChannel.write (buf); 
            buf.clear (); 
        } 

        // close the passage 
        sChannel.close (); 
    } 

    // server 
    @Test
     public  void Server () throws IOException {
         // acquisition channel 
        ServerSocketChannel = ssChannel ServerSocketChannel.open (); 

        // switch nonblocking 
        ssChannel.configureBlocking ( to false ); 

        // bind connection 
        ssChannel.bind ( new new the InetSocketAddress (9898 )); 

        // Get selector 
        selector selector = Selector.open ();

        // will be registered on the channel selector, and specify "monitor received event" 
        ssChannel.register (Selector, SelectionKey.OP_ACCEPT | SelectionKey.OP_READ); 

        // the polled have acquired selector "ready" event 
        while (selector.select ()> 0 ) { 

            // get all registered "selection key (ready listener events)" current selector 
            Iterator <SelectionKey> IT = selector.selectedKeys () Iterator ();. 

            the while (IT .hasNext ()) {
                 // get ready to "ready" is an event 
                SelectionKey SK = it.next (); 

                // determine what specific event ready 
                IF (sk.isAcceptable ()) {
                     // if "ready to receive" obtain client connection
                    Schannel = the SocketChannel ssChannel.accept (); 

                    // switch nonblocking 
                    sChannel.configureBlocking ( to false ); 

                    // the channel registered on the selector 
                    sChannel.register (Selector, SelectionKey.OP_READ); 
                } the else  IF (sk.isReadable ()) {
                     // get the current selector on the "read ready" state of the channel 
                    the SocketChannel Schannel = (the SocketChannel) sk.channel (); 

                    // read the data 
                    the ByteBuffer buf = ByteBuffer.allocate (1024 ); 

                    int len = 0 ;
                     while (( sChannel.read = len (buf))> 0 ) {
                        buf.flip();
                        System.out.println(new String(buf.array(), 0, len));
                        buf.clear();
                    }
                }

                // 移除当前 SelectionKey
                it.remove();
            }
        }
    }
}
View Code

2.UDP-DatagramChannel

package nio;

import org.junit.Test;

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;

public class TestNonBlockingNIO2 {

    @Test
    public void send() throws IOException{
        DatagramChannel dc = DatagramChannel.open();

        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{
        DatagramChannel dc = 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();
        }
    }
}
View Code

 

Three, Pipe (pipe)

Java NIO pipes are unidirectional data connection between the two threads. Pipe passage has a source and a sink channel. Sink channel data will be written, it is read from the source channels.

Package NiO; 

Import org.junit.Test; 

Import java.io.IOException;
 Import java.nio.ByteBuffer,;
 Import java.nio.channels.Pipe; 

public  class TestPipe { 

    @Test 
    public  void Test () throws IOException {
         // Get pipe 
        pipe pipe = Pipe.open (); 

        the ByteBuffer buf = ByteBuffer.allocate (1024 ); 
        buf.put ( "one-way data transmission pipe" .getBytes ()); 
        buf.flip (); 

        // the buffer data write pipe 
        Pipe.SinkChannel sinkChannel = pipe.sink();
        sinkChannel.write(buf);


        ByteBuffer buf2 = ByteBuffer.allocate(1024);
        // 读取缓冲区中的数据
        Pipe.SourceChannel sourceChannel = pipe.source();
        int len = sourceChannel.read(buf2);
        System.out.println(new String(buf2.array(), 0, len));

        sourceChannel.close();
        sinkChannel.close();
    }
}
View Code

 


https://mp.weixin.qq.com/s?__biz=Mzg3MjA4MTExMw==&mid=2247484746&idx=1&sn=c0a7f9129d780786cabfcac0a8aa6bb7

Guess you like

Origin www.cnblogs.com/jhxxb/p/11303947.html