• NIO案例


    一、NIO 同步非阻塞IO

    案例1:

     1.nio网络服务端程序,能不断接受客户端连接并读取客户端发来的数据

    package com.tenpower.nio.socket;
    
    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.Iterator;
    
    //网络服务器端程序
    public class NIOServer {
        public static void main(String[] args) throws  Exception{
            //1. 得到一个ServerSocketChannel对象  老大
            ServerSocketChannel serverSocketChannel=ServerSocketChannel.open();
            //2. 得到一个Selector对象   间谍
            Selector selector=Selector.open();
            //3. 绑定一个端口号
            serverSocketChannel.bind(new InetSocketAddress(9999));
            //4. 设置非阻塞方式
            serverSocketChannel.configureBlocking(false);
            //5. 把ServerSocketChannel对象注册给Selector对象
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            //6. 干活
            while(true){
                //6.1 监控客户端
                if(selector.select(2000)==0){  //nio非阻塞式的优势
                    System.out.println("Server:没有客户端搭理我,我就干点别的事");
                    continue;
                }
                //6.2 得到SelectionKey,判断通道里的事件
                Iterator<SelectionKey> keyIterator=selector.selectedKeys().iterator();
                while(keyIterator.hasNext()){
                    SelectionKey key=keyIterator.next();
                    if(key.isAcceptable()){  //客户端连接请求事件
                        System.out.println("OP_ACCEPT");
                        SocketChannel socketChannel=serverSocketChannel.accept();
                        socketChannel.configureBlocking(false);
                        socketChannel.register(selector,SelectionKey.OP_READ, ByteBuffer.allocate(1024));
                    }
                    if(key.isReadable()){  //读取客户端数据事件
                        SocketChannel channel=(SocketChannel) key.channel();
                        ByteBuffer buffer=(ByteBuffer) key.attachment();
                        channel.read(buffer);
                        System.out.println("客户端发来数据:"+new String(buffer.array()));
                    }
                    // 6.3 手动从集合中移除当前key,防止重复处理
                    keyIterator.remove();
                }
            }
        }
    }

    2.nio客户端程序

    package com.tenpower.nio.socket;
    
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.SocketChannel;
    
    //网络客户端程序
    public class NIOClient {
        public static void main(String[] args) throws  Exception{
            //1. 得到一个网络通道
            SocketChannel channel=SocketChannel.open();
            //2. 设置非阻塞方式
            channel.configureBlocking(false);
            //3. 提供服务器端的IP地址和端口号
            InetSocketAddress address=new InetSocketAddress("127.0.0.1",9999);
            //4. 连接服务器端
            if(!channel.connect(address)){
                while(!channel.finishConnect()){  //nio作为非阻塞式的优势
                    System.out.println("Client:连接服务器端的同时,我还可以干别的一些事情");
                }
            }
            //5. 得到一个缓冲区并存入数据
            String msg="hello,Server";
            ByteBuffer writeBuf = ByteBuffer.wrap(msg.getBytes());
            //6. 发送数据
            channel.write(writeBuf);
            System.in.read();
        }
    }

    连接上服务端后发送了一条数据,效果如下:

    案例2:多人聊天

    1.多人聊天服务端,接收客户端发来的数据,并能把数据广播给所有客户端

    package com.tenpower.nio.chat;
    
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.*;
    import java.text.SimpleDateFormat;
    import java.util.*;
    
    //聊天程序服务器端
    public class ChatServer {
        private ServerSocketChannel listenerChannel; //监听通道  老大
        private Selector selector;//选择器对象  间谍
        private static final int PORT = 9999; //服务器端口
    
        public ChatServer() {
            try {
                // 1. 得到监听通道  老大
                listenerChannel = ServerSocketChannel.open();
                // 2. 得到选择器  间谍
                selector = Selector.open();
                // 3. 绑定端口
                listenerChannel.bind(new InetSocketAddress(PORT));
                // 4. 设置为非阻塞模式
                listenerChannel.configureBlocking(false);
                // 5. 将选择器绑定到监听通道并监听accept事件
                listenerChannel.register(selector, SelectionKey.OP_ACCEPT);
                printInfo("Chat Server is ready.......");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        //6. 干活儿
        public void start() throws  Exception{
            try {
                while (true) { //不停监控
                    if (selector.select(2000) == 0) {
                        System.out.println("Server:没有客户端找我, 我就干别的事情");
                        continue;
                    }
                    Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                    while (iterator.hasNext()) {
                        SelectionKey key = iterator.next();
                        if (key.isAcceptable()) { //连接请求事件
                            SocketChannel sc=listenerChannel.accept();
                            sc.configureBlocking(false);
                            sc.register(selector,SelectionKey.OP_READ);
                            System.out.println(sc.getRemoteAddress().toString().substring(1)+"上线了...");
                        }
                        if (key.isReadable()) { //读取数据事件
                            readMsg(key);
                        }
                        //一定要把当前key删掉,防止重复处理
                        iterator.remove();
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        //读取客户端发来的消息并广播出去
        public void readMsg(SelectionKey key) throws Exception{
            SocketChannel channel=(SocketChannel) key.channel();
            ByteBuffer buffer=ByteBuffer.allocate(1024);
            int count=channel.read(buffer);
            if(count>0){
                String msg=new String(buffer.array());
                printInfo(msg);
                //发广播
                broadCast(channel,msg);
            }
        }
    
        //给所有的客户端发广播
        public void broadCast(SocketChannel except,String msg) throws Exception{
            System.out.println("服务器发送了广播...");
            for(SelectionKey key:selector.keys()){
                Channel targetChannel=key.channel();
                if(targetChannel instanceof SocketChannel && targetChannel!=except){
                    SocketChannel destChannel=(SocketChannel)targetChannel;
                    ByteBuffer buffer=ByteBuffer.wrap(msg.getBytes());
                    destChannel.write(buffer);
                }
            }
        }
    
        private void printInfo(String str) { //往控制台打印消息
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("[" + sdf.format(new Date()) + "] -> " + str);
        }
    
        public static void main(String[] args) throws Exception {
            new ChatServer().start();;
        }
    }

    2.多人聊天客户端,可向服务端发送数据,并能接受服务器广播的数据

    package com.tenpower.nio.chat;
    
    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.SocketChannel;
    import java.util.Iterator;
    import java.util.Set;
    
    //聊天程序客户端
    public class ChatClient {
        private final String HOST = "127.0.0.1"; //服务器地址
        private int PORT = 9999; //服务器端口
        private SocketChannel socketChannel; //网络通道
        private String userName; //聊天用户名
    
        public ChatClient() throws IOException {
            //1. 得到一个网络通道
            socketChannel=SocketChannel.open();
            //2. 设置非阻塞方式
            socketChannel.configureBlocking(false);
            //3. 提供服务器端的IP地址和端口号
            InetSocketAddress address=new InetSocketAddress(HOST,PORT);
            //4. 连接服务器端
            if(!socketChannel.connect(address)){
                while(!socketChannel.finishConnect()){  //nio作为非阻塞式的优势
                    System.out.println("Client:连接服务器端的同时,我还可以干别的一些事情");
            }
            }
            //5. 得到客户端IP地址和端口信息,作为聊天用户名使用
            userName = socketChannel.getLocalAddress().toString().substring(1);
            System.out.println("---------------Client(" + userName + ") is ready---------------");
        }
    
        //向服务器端发送数据
        public void sendMsg(String msg) throws Exception{
            if(msg.equalsIgnoreCase("bye")){
                socketChannel.close();
                return;
            }
            msg = userName + "说:"+ msg;
            ByteBuffer buffer=ByteBuffer.wrap(msg.getBytes());
            socketChannel.write(buffer);
        }
    
        //从服务器端接收数据
        public void receiveMsg() throws  Exception{
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            int size=socketChannel.read(buffer);
            if(size>0){
                String msg=new String(buffer.array());
                System.out.println(msg.trim());
            }
        }
    
    }

    3.运行客户端,并在主线程中发送数据,在另一个线程不断接受服务端的广播数据

    package com.tenpower.nio.chat;
    
    import java.io.IOException;
    import java.util.Scanner;
    
    //启动聊天程序客户端
    public class TestChat {
        public static void main(String[] args) throws Exception {
            ChatClient chatClient=new ChatClient();
    
            new Thread(){
                public void run(){
                    while(true){
                        try {
                            chatClient.receiveMsg();
                            Thread.sleep(2000);
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
    
            Scanner scanner=new Scanner(System.in);
            while (scanner.hasNextLine()){
                String msg=scanner.nextLine();
                chatClient.sendMsg(msg);
            }
    
        }
    }

    上述代码运行一次就是一个聊天客户端,可同时运行多个聊天客户端,聊天效果如下:

     

    二、AIO(NIO2.0) 异步非阻塞

    Proactor线线

  • 相关阅读:
    jQuery教程1,隐藏p标签
    Google 和 Microsoft 对 jQuery 的支持都很好。
    在编辑器中自动换行
    调用存储过程的一些方法
    jQuery教程2隐藏p标签内容按钮
    文件的复制,移动,创建
    网站中access数据库的备份和恢复
    修改文件名称
    生成静态网页,函数,引用过程
    网页中打印文本文件
  • 原文地址:https://www.cnblogs.com/naixin007/p/14486239.html
Copyright © 2020-2023  润新知