NIO实现服务端课客户端的通信

NIOServer

public class NIOServer {
    public static void main(String[] args) throws IOException {
        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.bind(new InetSocketAddress(6666));
        // 设置为非阻塞
        ssc.configureBlocking(false);
        // 定义多路复用选择器
        Selector sel = Selector.open();

        // 注册accept事件
        ssc.register(sel, SelectionKey.OP_ACCEPT);
        while(true) {
            // select()方法在没有用户发送请求事件的时候,这个方法会产生阻塞(直到有事件触发  阻塞才得以释放)
            sel.select();
            Set sks = sel.selectedKeys();  //  获取所有的请求的事件
            Iterator iter = sks.iterator();
            while(iter.hasNext()) {
                SelectionKey sk = iter.next();
                if(sk.isAcceptable()) {   // 建立连接请求的事件
                    /**
                     * 有人触发请求的时候,会在chanel()里面包装一个对象
                     */
                    ServerSocketChannel ssc1 = (ServerSocketChannel) sk.channel();
                    SocketChannel sc = ssc1.accept();
                    while(sc == null) {
                        sc = ssc1.accept();
                    }
                    sc.configureBlocking(false);  // 由于是非阻塞的,所以可能走到这段代码的时候,连接还没有建立
                    // 为sc注册read和write时间
                    // 0000 0001 OP_READ   读的事件
                    // 0000 0100 OP_WRITE  写的事件
                    /* 两者进行或运算   */
                    // 0000 0101    既有读的事件又有写的事件

                    // sc.register(sel, SelectionKey.OP_READ);  // 注册读的事件
                    // sc.register(sel, SelectionKey.OP_WRITE);  // 注册写的事件的事件

                    // 注册读跟写这两个事件可以写成
                    sc.register(sel, SelectionKey.OP_READ|SelectionKey.OP_WRITE);
                    System.out.println("提供服务的线程id是:" + Thread.currentThread().getId());
                }

                if(sk.isReadable()) {    // 客户端忘服务端写数据,就会触发服务端的读的事件 
                    // 获取连接对象
                    SocketChannel sc = (SocketChannel) sk.channel();    // 相当于把连接会话存到channel里了
                    ByteBuffer buf = ByteBuffer.allocate(10);
                    sc.read(buf);
                    System.out.println("服务器端读取到: " + new String(buf.array()));

                    // 当前是有读跟写这两个事件  现在需要去掉写事件
                    // 0000 0101     OP_READ 和  OP_WRITE
                    // 0000 0001     OP_READ

                    // 0000 0100    写操作 
                    /**
                     * sk.interestOps()     获取原来的事件
                     */
                    // 老师这里讲这个是告诉大家有这么一个算法
                    // sc.register(sel, SelectionKey.OP_WRITE);
                    sc.register(sel, sk.interestOps()&~SelectionKey.OP_READ);  // 按位做取反运算(把当前事件去掉)  把读事件去掉

                }
                if(sk.isWritable()) {    //   客户端读取操作时,触发了服务端的写的事件
                    // 获取SocketChannel
                    SocketChannel sc = (SocketChannel) sk.channel();
                    ByteBuffer buf = ByteBuffer.wrap("get".getBytes());
                    // System.out.println("写操作");
                    sc.write(buf);
                    // 去掉写事件
                    sc.register(sel, sk.interestOps()&~SelectionKey.OP_WRITE);
                }
                iter.remove();
            }
        }



    }
}

NIOClient

public class NIOClient {

    public static void main(String[] args) throws IOException {
        SocketChannel sc = SocketChannel.open();
        sc.configureBlocking(false);
        sc.connect(new InetSocketAddress("127.0.0.1", 6666));
        ByteBuffer buf = ByteBuffer.wrap("HelloWorld".getBytes());
        while(!sc.isConnected()) {
            sc.finishConnect();
        }
        sc.write(buf);
        System.out.println("客户端信息已经写出");

        // 接受数据
        ByteBuffer readBuf = ByteBuffer.allocate(3);
        sc.read(readBuf);
        System.out.println("客户端读到服务端传递过来的数据: " + new String(readBuf.array()));


        while(true);
    }
}

你可能感兴趣的:(大数据,大数据学习)