Java Nio Example

selector模型

使用一个线程去监控多个IO请求,如果哪一个IO数据准备完毕后就通知相应的线程来处理

select模型,它的基本原理是采用轮询和遍历的方式。也就是说,在客户端操作服务器时,会创建三种文件描述符,简称FD。分别是writefds(写描述符)、readfds(读描述符)和 exceptfds(异常描述符)

demo,让主线程监听IO事件然后进行处理

server

public class NioServerExample {

    public static void main(String[] args) throws IOException {

        Selector selector = getSelector();
        listen(selector);
    }

    public static Selector getSelector() throws IOException {
        Selector selector = Selector.open();

        //创建可选通道,设置非阻塞
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);

        //绑定通道到指定端口
        ServerSocket socket = serverSocketChannel.socket();
        socket.bind(new InetSocketAddress(8080));

        //向selector注册IO事件,首先注册SelectionKey.OP_ACCEPT让server accept监听
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        return selector;
    }

    public static void listen(Selector selector) throws IOException {
        while (selector.select() > 0) {
            Set selectionKeys = selector.selectedKeys();
            Iterator iterator = selectionKeys.iterator();
            if (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                iterator.remove();
                //判断IO事件类型进行处理
                process(selector, key);
            }
        }
    }

    private static void process(Selector selector, SelectionKey key) throws IOException {
        if (key.isAcceptable()) {
            System.out.println("事件类型 accept");
            ServerSocketChannel server = (ServerSocketChannel) key.channel();
            SocketChannel channel = server.accept();
            channel.configureBlocking(false);
            channel.register(selector, SelectionKey.OP_READ);
        } else if (key.isReadable()) {
            System.out.println("事件类型 read");
            SocketChannel channel = (SocketChannel) key.channel();
            ByteBuffer byteBuffer = ByteBuffer.allocate(500);
            int len = channel.read(byteBuffer);
            if (len > 0) {
                System.out.println(new String(byteBuffer.array(), 0, len));
                channel.register(selector, SelectionKey.OP_WRITE);
            } else {
                channel.close();
            }
            byteBuffer.clear();
        } else if (key.isWritable()) {
            System.out.println("事件类型 write");
            SocketChannel channel = (SocketChannel) key.channel();
            String str = "client fuck you I am Nio Server";
            channel.write(ByteBuffer.wrap(str.getBytes()));
            channel.close(); //向客户端发送数据后断开此通道连接

        }
    }
}

client

package org.example.io.branch.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.StandardSocketOptions;
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 NioClientExample {

    public static void main(String[] args) throws IOException, InterruptedException {
        Selector selector = getSelector();
        listen(selector);

    }

    private static Selector getSelector() throws IOException {
        Selector selector = Selector.open();
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.setOption(StandardSocketOptions.TCP_NODELAY, true);
        socketChannel.connect(new InetSocketAddress("127.0.0.1", 8080));
        socketChannel.configureBlocking(false);
        socketChannel.register(selector, SelectionKey.OP_WRITE);
        return selector;
    }

    private static void listen(Selector selector) throws IOException {
        while (selector.select() > 0) {
            Set selectionKeys = selector.selectedKeys();
            Iterator iterator = selectionKeys.iterator();
            if (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                iterator.remove();
                process(selector, key);
            }
        }
    }

    private static void process(Selector selector, SelectionKey key) throws IOException {
        if (key.isWritable()) {
            SocketChannel channel = (SocketChannel) key.channel();
            channel.configureBlocking(false);
            String info = "fuck you server I am Nio client";
            ByteBuffer byteBuffer = ByteBuffer.allocate(100);
            byteBuffer.put(info.getBytes());
            byteBuffer.flip();
            channel.write(byteBuffer);
            channel.register(selector, SelectionKey.OP_READ);
        } else if (key.isReadable()) {
            SocketChannel channel = (SocketChannel) key.channel();
            ByteBuffer byteBuffer = ByteBuffer.allocate(100);
            int len = channel.read(byteBuffer);
            if (len > 0) {
                System.out.println(new String(byteBuffer.array(), 0, len));
                channel.register(selector, SelectionKey.OP_WRITE);
            } else {
                channel.close();
            }
            byteBuffer.clear();
        }
    }
}

你可能感兴趣的:(javasocket编程nio)