NIO selector多路复用

public class NioServer {
    
    // 通道选择器,监控多个Channel并决定哪些channel能进行读或写,一个selector管理多个channel
    private Selector selector;
    
    public NioServer init(int port) throws IOException{
        // 创建一个ServerSocket通道
        ServerSocketChannel serverChannel = ServerSocketChannel.open();
        serverChannel.configureBlocking(false);
        serverChannel.socket().bind(new InetSocketAddress(port));
        // 获取通道选择器
        selector=Selector.open();
        // 将通道管理器与通道绑定,并为该通道注册SelectionKey.OP_ACCEPT事件
        // 只有当该事件到达时,Selector.select()会返回,否则一直阻塞。
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);
        return this;
    }
    
    public void listen() throws IOException{
        System.out.println("服务器端启动成功");
        // 使用轮询访问selector
        while(true){

            // 当有注册的事件到达时方法返回,否则阻塞。
            selector.select();
            
            // 获取selector中的迭代器,选中项为注册的事件
            Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
            
            while(ite.hasNext()){
                SelectionKey key = iter.next();
                // 删除已选key,防止重复处理
                iter.remove();

                // 客户端请求连接事件
                if(key.isAcceptable()){
                    ServerSocketChannel server = (ServerSocketChannel)key.channel();
                    // 获得客户端连接通道
                    SocketChannel channel = server.accept();
                    channel.configureBlocking(false);
                    // 向客户端发消息
                    channel.write(ByteBuffer.wrap(new String("send message to client").getBytes()));
                    // 与客户端连接成功后,为客户端通道注册SelectionKey.OP_READ事件
                    channel.register(selector, SelectionKey.OP_READ);
                    
                    System.out.println("客户端请求连接事件");
                }else if(key.isReadable()){ // 有可读数据事件
                    // 获取客户端传输数据可读取消息通道。
                    SocketChannel channel = (SocketChannel)key.channel();
                    // 创建读取数据缓冲器
                    ByteBuffer buffer = ByteBuffer.allocate(10);
                    int read = channel.read(buffer);
                    byte[] data = buffer.array();
                    String message = new String(data);
                    
                    System.out.println("receive message from client, size:" + buffer.position() + " msg: " + message);
                    // ByteBuffer outbuffer = ByteBuffer.wrap(("server.".concat(msg)).getBytes());
                    // channel.write(outbuffer);
                }
            }
        }
    }
    
    public static void main(String[] args) throws IOException {
        new NioServer().init(9981).listen();
    }
}

public class NioClient {

    private Selector selector;
    
    public NioClient init(String serverIp, int port) throws IOException{
        // 获取socket通道
        SocketChannel channel = SocketChannel.open();
        channel.configureBlocking(false);

        // 获得通道管理器
        selector=Selector.open();
        
        // 客户端连接服务器,需要调用channel.finishConnect();才能实际完成连接。
        channel.connect(new InetSocketAddress(serverIp, port));

        // 为该通道注册SelectionKey.OP_CONNECT事件
        channel.register(selector, SelectionKey.OP_CONNECT);
        return this;
    }
    
    public void listen() throws IOException{
        System.out.println("客户端启动");
        // 轮询访问selector
        while(true){

            // 选择注册过的io操作的事件(第一次为SelectionKey.OP_CONNECT)
            selector.select();
            Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
            while(iter.hasNext()){
                SelectionKey key = iter.next();

                // 删除已选的key,防止重复处理
                ite.remove();
                if(key.isConnectable()){
                    SocketChannel channel=(SocketChannel)key.channel();
                    
                    // 如果正在连接,则完成连接
                    if(channel.isConnectionPending()){
                        channel.finishConnect();
                    }
                    
                    channel.configureBlocking(false);
                    // 向服务器发送消息
                    channel.write(ByteBuffer.wrap(new String("send message to server.").getBytes()));
                    
                    // 连接成功后,注册接收服务器消息的事件
                    channel.register(selector, SelectionKey.OP_READ);
                    System.out.println("客户端连接成功");
                }else if(key.isReadable()){ // 有可读数据事件。
                    SocketChannel channel = (SocketChannel)key.channel();
                    
                    ByteBuffer buffer = ByteBuffer.allocate(10);
                    channel.read(buffer);
                    byte[] data = buffer.array();
                    String message = new String(data);
                    
                    System.out.println("recevie message from server:, size:" + buffer.position() + " msg: " + message);
                    // ByteBuffer outbuffer = ByteBuffer.wrap(("client.".concat(msg)).getBytes());
                    // channel.write(outbuffer);
                }
            }
        }
    }
    
    public static void main(String[] args) throws IOException {
        new NioClient().init("127.0.0.1", 9981).listen();
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值