Java-NIO-8聊天室


/**
 * NIO多路複用模型
 * reactor同意管理線程通過wait和notify來減少競爭
 */
public class NioServer {


    public static void main(String[] args) throws Exception {
        new NioServer().start();
    }

    private void start() throws Exception {
        //服務器管道
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //綁定端口
        serverSocketChannel.bind(new InetSocketAddress(9999));
        //非阻塞模式
        serverSocketChannel.configureBlocking(false);
        //選擇器
        Selector selector = Selector.open();
        //註冊事件
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT, "服務器");
        while (selector.select() > 0) {
            //處理註冊事件
            Set <SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator <SelectionKey> iterator = selectionKeys.iterator();
            while (iterator.hasNext()) {
                SelectionKey next = iterator.next();
                //移除事件表示這個事件我已經處理過了
                iterator.remove();
                //註冊事件
                if (next.isAcceptable()) {
                    acceptable(selector, serverSocketChannel);
                }
                //讀取事件
                if (next.isReadable()) {
                    //廣播所有客戶端
                    broadcast(next, selector);
                }
            }
        }
    }

    //廣播所有客戶端
    private void broadcast(SelectionKey selectionKey, Selector Selector) throws Exception {
        //獲取對應客戶但的channel
        SocketChannel channel = (SocketChannel) selectionKey.channel();
//        channel.register(Selector, SelectionKey.OP_READ);
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        String str = "";
        while (channel.read(buffer) > 0) {
            buffer.flip();
            str += Charset.forName("unicode").decode(buffer);
            buffer.clear();
        }
        String finalStr = str;
        Selector.keys().forEach(t -> {
            SelectableChannel selectableChannel = t.channel();
//            Object attachment = t.attachment();
//            System.out.println(attachment);
            if (selectableChannel instanceof SocketChannel && !selectableChannel.equals(channel)) {
                SocketChannel socketChannel = (SocketChannel) selectableChannel;
                try {
                    socketChannel.write(Charset.forName("unicode").encode(finalStr));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }


    private void acceptable(Selector selector, ServerSocketChannel serverSocketChannel) throws Exception {
        //獲取管道
        SocketChannel channel = serverSocketChannel.accept();
        channel.configureBlocking(false);
        //註冊
        SelectionKey register = channel.register(selector, SelectionKey.OP_READ);
//        register.attach("附件");
        channel.write(Charset.forName("unicode").encode("您已加入聊天室"));
    }
}


/**
 * @create 2019-05-14 16:01
 */
public class NioClient {

    public static void main(String[] args) throws Exception {
        new NioClient().start();
    }

    private void start() throws Exception {
        //獲取管道綁定服務器主機
        SocketChannel channel = SocketChannel.open(new InetSocketAddress("localhost", 9999));
        //選擇器
        Selector selector = Selector.open();
        channel.configureBlocking(false);
        channel.register(selector, SelectionKey.OP_READ, this.getClass().getSimpleName());
        //處理輸入語言
        ChatOut(channel);
        //處理服務器接收
        while (selector.select() > 0) {
            Set <SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator <SelectionKey> iterator = selectionKeys.iterator();
            if (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                iterator.remove();
                if (selectionKey.isReadable()) {
                    //接收服務器信息
                    brodacast(selectionKey, selector);
                }
            }
        }
    }

    /**
     * 處理輸入語言
     *
     * @param channel
     */
    private void ChatOut(SocketChannel channel) {
        ExecutorService pool = Executors.newFixedThreadPool(1);
        pool.submit(() -> {
            Scanner scanner = new Scanner(System.in);
            while (scanner.hasNextLine()) {
                String str = scanner.next();
                try {
                    channel.write(Charset.forName("unicode").encode(str));
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        });
    }

    //接收服務器信息
    private void brodacast(SelectionKey selectionKey, Selector selector) throws IOException {
        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
        Object attachment = selectionKey.attachment();
        System.out.println(attachment);
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        String str = "";
        while (socketChannel.read(buffer) > 0) {
            buffer.flip();
            str += Charset.forName("unicode").decode(buffer);
            buffer.clear();
        }
        System.out.println(str);
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章