NIO简单实现

NIO三件套:Buffer:数据载体、channel:载体通道、Selector:选择器。

NIO三种状态:
如果无客户端请求连接,直到有客户端请求连接之前select()方法一直被阻塞状态。
如果有客户端请求连接,但是客户端连接的请求没有被处理,此时select()方法是非阻塞状态。
如果有客户端请求连接,客户端连接的请求被处理,此时select()方法是阻塞状态。

 

服务端

package com.sunny.service;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

public class SelectorServerSocketTest {

    // 模拟NIO 这里一个主线程可以处理三个客户端的请求

    public static void main(String[] args) {
        try (
                // 获取一个选择器
                Selector selector = Selector.open();
                // 获取多个ServerSocketChannel
                ServerSocketChannel serverSocketChannel6666 = ServerSocketChannel.open();
                ServerSocketChannel serverSocketChannel7777 = ServerSocketChannel.open();
                ServerSocketChannel serverSocketChannel8888 = ServerSocketChannel.open();
        ) {
            serverSocketChannel6666.bind(new InetSocketAddress(6666));
            serverSocketChannel7777.bind(new InetSocketAddress(7777));
            serverSocketChannel8888.bind(new InetSocketAddress(8888));

            // ServerSocketChannel默认是阻塞,因为要实现Selector同步非阻塞,因此现需要将serverSocketChannel6 设置成非阻塞
            serverSocketChannel6666.configureBlocking(false);
            serverSocketChannel7777.configureBlocking(false);
            serverSocketChannel8888.configureBlocking(false);

            // 将多少ServerSocketChannel注册到一个选择器上
            // 只能注册SelectionKey.OP_ACCEPT ,也就是接受就绪事件
            serverSocketChannel6666.register(selector, SelectionKey.OP_ACCEPT);
            serverSocketChannel7777.register(selector, SelectionKey.OP_ACCEPT);
            serverSocketChannel8888.register(selector, SelectionKey.OP_ACCEPT);


            int registerChannelSize = selector.keys().size();
            System.out.println("当前选择器上注册" + registerChannelSize + "个服务器管道");

            int connectionChannelSize = selector.selectedKeys().size();
            System.out.println("当前选择器上连接了" + connectionChannelSize + "个服务器管道");

            //处理客户端请求
            // 轮询访问selector
            while (true) {
                System.out.println("服务器:服务器开始等待客户端连接");
                selector.select();
                System.out.println("服务器:服务器已接受到客户端连接");

                connectionChannelSize = selector.selectedKeys().size();
                System.out.println("当前选择器上连接了" + connectionChannelSize + "个服务器管道");

                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> selectionKeysIterator = selectionKeys.iterator();
               
                // 获得selector中选中的项的迭代器,选中的项为注册的事件
                while (selectionKeysIterator.hasNext()) {
                    SelectionKey selectionKey = selectionKeysIterator.next();
                    ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    ByteBuffer clientRequestByteBuffer = ByteBuffer.allocate(1024);
                    int clientRequestLength = socketChannel.read(clientRequestByteBuffer);
                    String clientRequestDate = new String(clientRequestByteBuffer.array(), 0, clientRequestLength);
                    System.out.println("服务器:客户端请求内容:" + clientRequestDate);

                    // 根据不同请求响应不同结果
                    String responseDateByteRequestDate = getResponseDateByteRequestDate(clientRequestDate);
                    ByteBuffer serverResponseByteBuffer = ByteBuffer.allocate(1024);
                    serverResponseByteBuffer.put(responseDateByteRequestDate.getBytes());
                    serverResponseByteBuffer.flip();
                    socketChannel.write(serverResponseByteBuffer);
                    System.out.println("服务器:服务器响应给客户端的是"+responseDateByteRequestDate);
                    System.out.println();
                    // 处理完以后删除已处理的
                    selectionKeysIterator.remove();

                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static String getResponseDateByteRequestDate(String requestDate) {
        String responstDate = null;
        if ("跟光磊学习Java怎么样".equals("跟光磊学习Java怎么样")) {
            responstDate = "很棒";
        } else if ("跟光磊学习前段怎么样".equals("跟光磊学习前段怎么样")) {
            responstDate = "很好";
        } else if ("跟光磊学习Linux怎么样".equals("跟光磊学习Linux怎么样")) {
            responstDate = "好吸收";
        }
        return responstDate;
    }
}

客户端

package com.sunny.service;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class SelectorSocketTest {

    public static void main(String[] args) {

        Map<Integer, String> clientRequest = new HashMap<>();
        clientRequest.put(6666,"跟光磊学习Java怎么样?");
        clientRequest.put(7777,"跟光磊学习前段怎么样?");
        clientRequest.put(8888,"跟光磊学习Linux怎么样?");
        Set<Map.Entry<Integer, String>> clientRequestEntrySet = clientRequest.entrySet();
        for (Map.Entry<Integer, String> integerStringEntry : clientRequestEntrySet) {
            Integer clientRequestPort = integerStringEntry.getKey();
            String clientRequestDate = integerStringEntry.getValue();
            try(
                    SocketChannel socketChannel = SocketChannel.open();
            ) {
                socketChannel.connect(new InetSocketAddress(clientRequestPort));
                System.out.println("客户端:客户端连接服务器"+clientRequestPort);

                ByteBuffer clientRequestByteBuffer = ByteBuffer.allocate(1024);
                clientRequestByteBuffer.put(clientRequestDate.getBytes());
                clientRequestByteBuffer.flip();
                socketChannel.write(clientRequestByteBuffer);
                System.out.println("客户端:客户端发送请求给"+clientRequestPort+"的服务器,请求内容:"+clientRequestDate);

                // 接收客户端响应的信息
                ByteBuffer serverByteBuffer = ByteBuffer.allocate(1024);
                int serverByteBufferLength = socketChannel.read(serverByteBuffer);
                String serverResponseDate = new String(serverByteBuffer.array(), 0, serverByteBufferLength);
                System.out.println("客户端:客户端接收服务器响应数据:"+serverResponseDate);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

 

posted @ 2022-02-13 21:03  爵士灬  阅读(74)  评论(0编辑  收藏  举报