入门:初探NIO原理及使用

//Socket服务器端
public class NIOServer03 {
    public static void main(String[] args) throws IOException {
        //创建选择器(多路复用器)对象
        Selector selector = Selector.open();

        //创建Socket服务端通道对象
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

        //配置为非阻塞
        serverSocketChannel.configureBlocking(false);

        //将Socket服务端通道的对象注册到选择器上,并指定其通道对象的注册事件为接收事件
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        //指定Socket服务端的IP地址和端口
        InetSocketAddress address = new InetSocketAddress("127.0.0.1", 8888);

        //绑定地址
        serverSocketChannel.bind(address);

        //服务端需要一直建立连接保存与客户端通讯,所以这里设为死循环
        while(true){
            //开启选择器进行监听,这里至少选择一个通道,如果该选择器是关闭抛出ClosedSelectorException
            selector.select();

            //返回此选择器的选定键集(注册的事件)。如果该选择器是关闭抛出ClosedSelectorException
            Set<SelectionKey> selectionKeys = selector.selectedKeys();

            //用迭代器遍历选定键集
            Iterator<SelectionKey> keyIterator = selectionKeys.iterator();

            while (keyIterator.hasNext()) {
                SelectionKey key = keyIterator.next();

                //如果key的注册事件为接收事件时执行
                if(key.isAcceptable()){

                    //返回为其创建此密钥(key)的通道
                    ServerSocketChannel socketChannelByKey = (ServerSocketChannel) key.channel();

                    /**
                     * 接收与此通道的套接字建立的连接
                     * 如果没有挂起的连接,会立即返回null,否则它将无限期阻塞,直到有新连接或发生I/O错误
                     * 返回新连接的套接字通道
                     */
                    SocketChannel socketChannel = socketChannelByKey.accept();

                    //设为非阻塞
                    socketChannel.configureBlocking(false);

                    //将该套接字通道注册为读取事件
                    socketChannel.register(selector, SelectionKey.OP_READ);
                }else if(key.isReadable()){ //如果key的注册事件为读取事件时执行

                    //返回为其创建此密钥(key)的通道
                    SocketChannel socketChannel = (SocketChannel) key.channel();

                    //解析读取该通道上的数据并返回打印
                    String data = readDataFromSocketChannel(socketChannel);

                    System.out.println("return data:"+data);

                    //关闭该套接字通道
                    socketChannel.close();
                }

                //没有其他注册事件则移除该key键
                keyIterator.remove();
            }
        }

    }

    private static String readDataFromSocketChannel(SocketChannel socketChannel) throws IOException {
        StringBuilder data=new StringBuilder();

        //分配一个新的字节缓冲区,新缓冲区的位置将为零,它的限制将是它的容量,即1024(B),如果容量为负整数则抛出IllegalArgumentException
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

        while(true){    //循环读取数据
            //清空缓冲区
            //byteBuffer.clear();

            //将Socket通道中数据读入字节缓冲区中
            int read = socketChannel.read(byteBuffer);

            if(read == -1){
                //缓冲区不存在数据时停止循环
                break;
            }

            //翻转这个缓冲区.限制设置为当前位置
            byteBuffer.flip();

            //返回此缓冲区的限制
            int limit = byteBuffer.limit();

            //设置字符数组,存储读取的数据
            char[] dst=new char[limit];

            for (int i = 0; i < limit; i++) {
                //获取读取的数据
                dst[i]= (char) byteBuffer.get(i);
            }

            //存入StringBuilder对象中
            data.append(dst);

            //byteBuffer.clear();
        }
        return data.toString();
    }
}
//Socket客户端
public class NIOClient03 {
    public static void main(String[] args) throws IOException {

        //根据IP地址与端口与Socket服务器建立连接
        Socket socket=new Socket("127.0.0.1",8888);

        //获取socket中输出流并写入
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("hello world".getBytes());

        //关闭输出流
        outputStream.close();

    }
}

执行结果:
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值