zoukankan      html  css  js  c++  java
  • 02_NIO简单实例

    【一个用NIO实现的客户端向服务端单向通信的例子】

    【服务端程序】

    package com.nio.test;
    
    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.ServerSocketChannel;
    import java.nio.channels.SocketChannel;
    import java.util.Iterator;
    
    /**
     * Created by cuixinjie on 2018/5/30.
     */
    public class Server implements Runnable{
    
        //1.多路复用器(管理所有的Channel)
        private Selector selector;
        //2.建立缓冲区
        private ByteBuffer readBuffer = ByteBuffer.allocate(1024);
    
        public Server(int port){
            try {
                //1.打开多路复用器
                this.selector = Selector.open();
                //2.打开服务端通道Channel
                ServerSocketChannel ssc = ServerSocketChannel.open();
                //3.设置服务器通道为非阻塞模式
                ssc.configureBlocking(false);
                //4.绑定地址
                ssc.bind(new InetSocketAddress(port));
                //5.把服务器通道ssc注册到多路复用器selector上,并且监听阻塞事件
                ssc.register(this.selector, SelectionKey.OP_ACCEPT);
    
                System.out.println("服务端已启动,监听port:"+port);
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    
        @Override
        public void run() {
            while (true){
                try{
                    //1.让多路复用器开始监听
                    this.selector.select();
                    //2.返回多路复用器已经选择的Key结果集
                    Iterator<SelectionKey> keys = this.selector.selectedKeys().iterator();
                    //3.进行遍历
                    while (keys.hasNext()){
                        //4.获取一个选择的的元素
                        SelectionKey key = keys.next();
                        //5.直接从容器中移除
                        keys.remove();
                        //6.如果是有效的
                        if(key.isValid()){
                            //7.如果是阻塞状态
                            if(key.isAcceptable()){
                                this.accept(key);
                            }
                            //8.如果是可读状态
                            if(key.isReadable()){
                                this.read(key);
                            }
                        }
                    }
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    
        private void accept(SelectionKey key){
            try{
                //1.获取服务端通道
                ServerSocketChannel ssc  = (ServerSocketChannel)key.channel();
                //2.执行阻塞方法
                SocketChannel sc = ssc.accept();  //注意:这里会一直阻塞到客户端的请求过来!
                //3.设置阻塞模式
                sc.configureBlocking(false);
                //4.注册到多路复用器上,并设置读取标识
                sc.register(this.selector,SelectionKey.OP_READ);
    
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    
        private void read(SelectionKey key ){
            try{
                //1.清空缓冲区旧的数据
                this.readBuffer.clear();
                //2.获取之前注册的Socket通道对象
                SocketChannel sc = (SocketChannel)key.channel();
                //3.读取数据
                int count = sc.read(this.readBuffer);
                //4.如果没有数据
                if(count== -1){
                    key.channel().close();
                    key.cancel();
                    return;
                }
                //5.有数据则进行数据读取,读取之前需要进行复位方法(把position 和 limit进行复位)
                this.readBuffer.flip();
                //6.根据缓冲区的数据长度创建相应大小的byte数组,接收缓冲区的数据
                byte[] bytes = new byte[this.readBuffer.remaining()];
                //7.接收缓冲区数据
                this.readBuffer.get(bytes);
                //8.打印结果
                String body = new String(bytes).trim();
                System.out.println("服务端收到客户端的内容为:"+body);
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            new Thread(new Server(8765)).start();
        }
    }

    【客户端程序】

    package com.nio.test;
    
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.SocketChannel;
    
    /**
     * Created by cuixinjie on 2018/5/30.
     */
    public class Client {
    
    
        public static void main(String[] args) {
            //创建连接的地址
            InetSocketAddress address = new InetSocketAddress("127.0.0.1",8765);
    
            //声明连接通道
            SocketChannel sc = null;
    
            //建立缓冲区
            ByteBuffer buf = ByteBuffer.allocate(1024);
    
            try{
                //打开通道
                sc = SocketChannel.open();
                //进行连接
                sc.connect(address);
                while(true){
                    //定义一个字节数组,然后使用系统录入功能
                    byte[] bytes = new byte[1024];
                    System.out.print("客户端发送的数据为:");
                    System.in.read(bytes);
    
                    //把数据的数据放入缓冲区中
                    buf.put(bytes);
                    //对缓冲区进行复位
                    buf.flip();
                    //写出数据
                    sc.write(buf);
                    //清空缓冲区数据
                    buf.clear();
                }
            }catch (IOException e){
                e.printStackTrace();
            }finally {
                if(null!=sc){
                    try{
                        sc.close();
                    }catch (IOException e){
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    【运行结果】

    1.先启动服务端

    2.再启动客户端,并输入需要传输的数据

    3.再查看服务端接受的数据

  • 相关阅读:
    python多线程
    python网络编程-udp/tcp通信
    通达OA未授权任意文件上传及文件包含导致远程代码执行漏洞
    星盟安全awd复盘20200314
    Axublog1.1.0代码审计
    回调函数绕过D盾小套路
    php7.1后webshell免杀的去路
    GO语言 特性概要
    Openstack 笔记概要
    大数据--基本理论知识(1)
  • 原文地址:https://www.cnblogs.com/HigginCui/p/9114266.html
Copyright © 2011-2022 走看看