[Yugong series] January 2022 Java Teaching Course 69-NIO combined with Scott's network communication

Article catalog

I Network communication of NIO combined with Scott

1.NIO channel client

  • Client implementation steps
    1. Open channel
    2. Specify the IP and port number
    3. Write data
    4. Release resources
  • Sample code
public class NIOClient {
    public static void main(String[] args) throws IOException {
        //1. Open the channel
        SocketChannel socketChannel = SocketChannel.open();

        //2. Specify the IP and port number
        socketChannel.connect(new InetSocketAddress("127.0.0.1",10000));

        //3. Write data
        ByteBuffer byteBuffer = ByteBuffer.wrap("NIO combination Scoket Network communication".getBytes());
        socketChannel.write(byteBuffer);

        //4. Release resources
        socketChannel.close();
    }
}

2. NIO channel server

  • NIO channel

Server channel

It is only responsible for establishing, not transmitting data

Client channel

Establish and transfer data to the server

buffer

The data sent by the client is in the buffer

The client channel created inside the server channel

Equivalent to an extension of the client channel used to transfer data

  • Server implementation steps

Open a server channel

Bind the corresponding port number

The channel is blocked by default and needs to be set to non blocking

There is no guard at this time, so you need to often check whether there is a connection sent?

If a client is connected, create another client channel inside the server channel, which is equivalent to the extension of the client channel

Get the data passed by the client and put the data in the buffer byteBuffer1

Write back data to the client

Release resources

  • Sample code
public class NIOServer {
    public static void main(String[] args) throws IOException {
//        1. Open a server channel
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//        2. Bind the corresponding port number
        serverSocketChannel.bind(new InetSocketAddress(10000));
//        3. The channel is blocked by default and needs to be set to non blocking
            //If true is passed, the channel is set to blocked channel Default value
            //If false is passed, the channel is set to a non blocking channel
        serverSocketChannel.configureBlocking(false);
//        4. There is no guard at this time, so you need to often check whether there is a connection sent?
        while (true) {
//        5. If a client is connected, create another client channel inside the server channel, which is equivalent to the extension of the client channel
            //At this time, the channel has been set to non blocking
            //Therefore, when calling the method, if there is a client to connect, a SocketChannel object will be created
            //If there is no client to connect when calling the method, it will return a null
            SocketChannel socketChannel = serverSocketChannel.accept();
            //System.out.println(socketChannel);
            if(socketChannel != null){
//        6. The client passes the buffer to the server through the channel to the extension channel socketChannel
//        7. The server creates an empty buffer to load data and output it
                ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                //Get the passed data and put them into the byteBuffer buffer
                //Return value:
                    //Positive number: indicates the number of valid bytes read this time
                    //0: indicates that no valid bytes are read this time
                    //-1: it means the end is read
                int len = socketChannel.read(byteBuffer);
                System.out.println(new String(byteBuffer.array(),0,len));
              //8. Release resources
                socketChannel.close();
            }
        }
    }
}

3. NIO channel exercise

client

  • Implementation steps
    1. Open channel
    2. Specify the IP and port number
    3. Write data
    4. Read data written back by the server
    5. Release resources
  • Sample code
public class Clinet {
    public static void main(String[] args) throws IOException {
        // 1. Open the channel
        SocketChannel socketChannel = SocketChannel.open();
        // 2. Specify the IP and port number
        socketChannel.connect(new InetSocketAddress("127.0.0.1",10000));
        // 3. Write data
        ByteBuffer byteBuffer1 = ByteBuffer.wrap("NIO combination Scoket Network communication two-way communication version".getBytes());
        socketChannel.write(byteBuffer1);
  		// Manual write end flag
        socketChannel.shutdownOutput();

        System.out.println("The data has been written to the server");
        // 4. Read the data written back by the server
        ByteBuffer byteBuffer2 = ByteBuffer.allocate(1024);
        int len;
        while((len = socketChannel.read(byteBuffer2)) != -1){
            byteBuffer2.flip();
            System.out.println(new String(byteBuffer2.array(),0,len));
            byteBuffer2.clear();
        }
        // 5. Release resources
        socketChannel.close();
    }
}
  • Server

Implementation steps

Open a server channel

Bind the corresponding port number

The channel is blocked by default and needs to be set to non blocking

There is no guard at this time, so you need to often check whether there is a connection sent?

If a client is connected, create another client channel inside the server channel, which is equivalent to the extension of the client channel

Get the data passed by the client and put the data in the buffer byteBuffer1

Write back data to the client

Release resources

  • Sample code
public class Clinet {
    public static void main(String[] args) throws IOException {
        // 1. Open the channel
        SocketChannel socketChannel = SocketChannel.open();
        // 2. Specify the IP and port number
        socketChannel.connect(new InetSocketAddress("127.0.0.1",10000));
        // 3. Write data
        ByteBuffer byteBuffer1 = ByteBuffer.wrap("NIO combination Scoket Network communication two-way communication version".getBytes());
        socketChannel.write(byteBuffer1);
  		// Manual write end flag
        socketChannel.shutdownOutput();

        System.out.println("The data has been written to the server");
        // 4. Read the data written back by the server
        ByteBuffer byteBuffer2 = ByteBuffer.allocate(1024);
        int len;
        while((len = socketChannel.read(byteBuffer2)) != -1){
            byteBuffer2.flip();
            System.out.println(new String(byteBuffer2.array(),0,len));
            byteBuffer2.clear();
        }
        // 5. Release resources
        socketChannel.close();
    }
}
  • Server

Implementation steps

Open a server channel

Bind the corresponding port number

The channel is blocked by default and needs to be set to non blocking

There is no guard at this time, so you need to often check whether there is a connection sent?

If a client is connected, create another client channel inside the server channel, which is equivalent to the extension of the client channel

Get the data passed by the client and put the data in the buffer byteBuffer1

Write back data to the client

Release resources

  • Sample code
public class Sever {
    public static void main(String[] args) throws IOException {
        // 1. Open a server channel
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        // 2. Bind the corresponding port number
        serverSocketChannel.bind(new InetSocketAddress(10000));
        // 3. The channel is blocked by default and needs to be set to non blocking
        serverSocketChannel.configureBlocking(false);
        // 4. There is no guard at this time, so you need to often check whether there is a connection sent?
        while(true){
            //  5. If a client is connected, create another client channel inside the server channel, which is equivalent to the extension of the client channel
            SocketChannel socketChannel = serverSocketChannel.accept();
            if(socketChannel != null){
                System.out.println("At this time, there is a client to connect");
                // 6. Get the data passed by the client and put the data in the buffer byteBuffer1
                ByteBuffer byteBuffer1 = ByteBuffer.allocate(1024);
                //socketChannel.read(byteBuffer1);
                int len;
                //For buffers
                    //If you get data from add data - > flip
                    //If you get data from ---- > add data clear
                while((len = socketChannel.read(byteBuffer1)) != -1){
                    byteBuffer1.flip();
                    System.out.println(new String(byteBuffer1.array(),0,len));
                    byteBuffer1.clear();
                }

                System.out.println("Finished receiving data,Ready to start writing data back to the client");
                // 7. Write back data to the client
                ByteBuffer byteBuffer2 = ByteBuffer.wrap("Here you are!!".getBytes());
                socketChannel.write(byteBuffer2);
                // 8. Release resources
                socketChannel.close();
            }
        }
    }
}

4. NIO channel practice optimization

  • Existing problems When the client channel obtained by the server is read, if the end tag is not read, it will be blocked all the time
  • Solution Set the client channel obtained internally by the server to non blocking
  • Sample code
// client
public class Clinet {
    public static void main(String[] args) throws IOException {
        SocketChannel socketChannel = SocketChannel.open();

        socketChannel.connect(new InetSocketAddress("127.0.0.1",10000));

        ByteBuffer byteBuffer1 = ByteBuffer.wrap("NIO combination Scoket Network communication".getBytes());
        socketChannel.write(byteBuffer1);

        System.out.println("The data has been written to the server");

        ByteBuffer byteBuffer2 = ByteBuffer.allocate(1024);
        int len;
        while((len = socketChannel.read(byteBuffer2)) != -1){
            System.out.println("Client receives write back data");
            byteBuffer2.flip();
            System.out.println(new String(byteBuffer2.array(),0,len));
            byteBuffer2.clear();
        }
        socketChannel.close();
    }
}
// Server
public class Sever {
    public static void main(String[] args) throws IOException {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

        serverSocketChannel.bind(new InetSocketAddress(10000));

        serverSocketChannel.configureBlocking(false);

        while(true){
            SocketChannel socketChannel = serverSocketChannel.accept();
            if(socketChannel != null){
                System.out.println("At this time, there is a client to connect");
              	// Set the client channel obtained internally by the server to non blocking
                socketChannel.configureBlocking(false);
                //Get the data passed by the client and put the data in the buffer byteBuffer1
                ByteBuffer byteBuffer1 = ByteBuffer.allocate(1024);
                //socketChannel.read(byteBuffer1);
                int len;
                //For buffers
                    //If you get data from add data - > flip
                    //If you get data from ---- > add data clear
                while((len = socketChannel.read(byteBuffer1)) > 0){
                    System.out.println("The server receives and sends data");
                    byteBuffer1.flip();
                    System.out.println(new String(byteBuffer1.array(),0,len));
                    byteBuffer1.clear();
                }

                System.out.println("Data reception completed,Ready to start writing data back to the client");

                ByteBuffer byteBuffer2 = ByteBuffer.wrap("Here you are!!!".getBytes());
                socketChannel.write(byteBuffer2);

                socketChannel.close();
            }
        }
    }
}

5. NIO selector

  • summary The selector can monitor the status of the channel and multiplex
  • Selector object
    • Selector Selector object
    • SelectionKey Bound key
    • SelectableChannel Channels that can use selectors
      • SocketChannel
      • ServerSocketChannel

6. NIO selector rewriting server

  • Implementation steps
    1. Open a server channel
    2. Bind the corresponding port number
    3. The channel is blocked by default and needs to be set to non blocking
    4. Open a selector (doorman)
    5. Bind the selector to the server channel and monitor whether the server is ready
    6. If there is a client to connect, the uncle will traverse all the server channels. Whoever is ready will connect After connecting, create a client extension channel inside the server channel
    7. If the client transmits the data, the uncle will traverse all the extension channels. Who is ready and who will receive the data
  • code implementation
// client
public class Clinet {
    public static void main(String[] args) throws IOException {
        SocketChannel socketChannel = SocketChannel.open();

        socketChannel.connect(new InetSocketAddress("127.0.0.1",10000));

        ByteBuffer byteBuffer1 = ByteBuffer.wrap("NIO combination Scoket Network communication".getBytes());
        socketChannel.write(byteBuffer1);

        System.out.println("The data has been written to the server");

        ByteBuffer byteBuffer2 = ByteBuffer.allocate(1024);
        int len;
        while((len = socketChannel.read(byteBuffer2)) != -1){
            System.out.println("Client receives write back data");
            byteBuffer2.flip();
            System.out.println(new String(byteBuffer2.array(),0,len));
            byteBuffer2.clear();
        }
        socketChannel.close();
    }
}
// Server
public class Server {
    public static void main(String[] args) throws IOException {
        //1. Open the server channel
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //2. Bind this channel to a port
        serverSocketChannel.bind(new InetSocketAddress(10000));
        //3. Set the channel to non blocking
        serverSocketChannel.configureBlocking(false);
        //4. Open a selector
        //Selector --- selector
//        SelectionKey --- the token returned after binding the channel
  //      SelectableChannel --- a channel that can use a selector
        Selector selector = Selector.open();
        //5. Bind selector and server channel
        serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT);

        while(true){
            System.out.println("11");
            //The selector monitors the status of the client channel
            //6. The return value indicates how many clients are connected at this time
            int count = selector.select();
            System.out.println("222");
            if(count != 0){
                System.out.println("There is a client to connect");
                //7. It will traverse all server channels See who is ready, who is ready, let who connect
                //Get the tokens of all server channels, put them into a collection, and return the collection
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
                while(iterator.hasNext()){
                    //selectionKey indicates the token of each server channel in turn
                    SelectionKey selectionKey = iterator.next();
                    if(selectionKey.isAcceptable()){
                        //A ready server channel can be obtained through a token
                        ServerSocketChannel ssc = (ServerSocketChannel) selectionKey.channel();
                        //Extended channel of client
                        SocketChannel socketChannel = ssc.accept();
                        //Set the client extension channel to non blocking
                        socketChannel.configureBlocking(false);
                        socketChannel.register(selector,SelectionKey.OP_READ);
                        //When the client connects, all the steps have been completed
                    }else if(selectionKey.isReadable()){
                        //The current channel is ready for reading (extended channel)
                        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                        ByteBuffer byteBuffer1 = ByteBuffer.allocate(1024);
                        //socketChannel.read(byteBuffer1);
                        int len;
                        while((len = socketChannel.read(byteBuffer1)) > 0){
                            byteBuffer1.flip();
                            System.out.println(new String(byteBuffer1.array(),0,len));
                            byteBuffer1.clear();
                        }
                        //Write back data to client
                        socketChannel.write(ByteBuffer.wrap("Here you are!!!".getBytes()));
                        socketChannel.close();
                    }
                    iterator.remove();
                }
            }
        }
    }
}

Added by Runilo on Wed, 19 Jan 2022 13:36:56 +0200