JAVA NIO Selector构建简单服务器

JAVA NIO Selector构建简单服务器

ServerSocketChannel + Selector

NIOServer.java

public class NIOServer implements Runnable{

    private int clientNum = 0;
    private int bufferSize = 12;

    @Override
    public void run() {

        try {
            // 创建通道和选择器
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            Selector selector = Selector.open();
            InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 5500);
            serverSocketChannel.socket().bind(inetSocketAddress);
            // 设置通道非阻塞 绑定选择器
            serverSocketChannel.configureBlocking(false);
            /*
             * ServerSocketChannel只有accept
             */
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT).attach("server");
            System.out.println("Server started .... port:5500");

            while(true) {
                int readyChannels = selector.select();
                if(readyChannels == 0) continue;
                Set selectedKeys = selector.selectedKeys();
                Iterator keyIterator = selectedKeys.iterator();
                while(keyIterator.hasNext()) {

                    SelectionKey key = (SelectionKey)keyIterator.next();
                    // 判断是哪个事件
                    if(key.isAcceptable()) {// 客户请求连接
                        System.out.println(key.attachment()+ " - 接受请求事件");
                        ++clientNum;
                        // 获取通道 接受连接,
                        // 设置非阻塞模式(必须),同时需要注册 读写数据的事件,这样有消息触发时才能捕获
                        SocketChannel socketChannel = ((ServerSocketChannel) key.channel()).accept();

                        socketChannel.configureBlocking(false);
                        socketChannel.register(selector, SelectionKey.OP_READ).attach("accept"+clientNum);

                        System.out.println(key.attachment() + " - 已连接");
                    } else if (key.isConnectable()) {
                        System.out.println(key.attachment()+ " - 连接事件");
                    } else if (key.isReadable()) {
                        System.out.println(key.attachment()+ " - 读数据事件");
                        SocketChannel clientChannel=(SocketChannel)key.channel();
                        ByteBuffer receiveBuf = ByteBuffer.allocate(bufferSize);
                        clientChannel.read(receiveBuf);
                        System.out.println(key.attachment()+ " - 读取数据:" + getString(receiveBuf));
                    } else if (key.isWritable()) {
                        System.out.println(key.attachment()+ " - 写数据事件");
                        SocketChannel clientChannel = (SocketChannel) key.channel();
                        ByteBuffer sendBuf = ByteBuffer.allocate(bufferSize);
                        String sendText = "helloc";
                        sendBuf.put(sendText.getBytes());
                        sendBuf.flip();        //写完数据后调用此方法
                        clientChannel.write(sendBuf);
                    }
                    keyIterator.remove();
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public String getString(ByteBuffer buffer){
        StringBuffer builder = new StringBuffer("");
        try{
            for(int i = 0; i<buffer.position();i++){
                builder.append((char)buffer.get(i));
            }
            return builder.toString();
        }catch (Exception ex){
            ex.printStackTrace();
            return builder.toString();
        }
    }
}

SocketChannel

NIOClient.java

public class NIOClient implements Runnable {

    private String tag = "client";
    private ByteBuffer readBuffer;
    private ByteBuffer writeBuffer;
    private boolean isConnected = false;
    private int bufferSize = 12;

    public NIOClient(String tag){
        this.tag = tag;
        readBuffer = ByteBuffer.allocate(bufferSize);
        writeBuffer = ByteBuffer.allocate(bufferSize);
    }

    @Override
    public void run() {

        try {

            Selector selector = Selector.open();

            SocketChannel socketChannel  = SocketChannel.open();

            socketChannel.configureBlocking(false);
            socketChannel.connect(new InetSocketAddress("127.0.0.1", 5500));
            socketChannel.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ|SelectionKey.OP_WRITE).attach(tag);

            System.out.println(tag+" connect .... port:5500");

            while(true) {
                int readyChannels = selector.select();
                if(readyChannels == 0) continue;
                Set selectedKeys = selector.selectedKeys();
                Iterator keyIterator = selectedKeys.iterator();
                while(keyIterator.hasNext()) {

                    SelectionKey key = (SelectionKey)keyIterator.next();
                    // 判断是哪个事件
                    if(key.isAcceptable()) {// 客户请求连接
                        System.out.println(key.attachment()+ "is accepted by server");

                    } else if (key.isConnectable()) {
                        System.out.println(key.attachment()+ " connect ");
                        SocketChannel channel = (SocketChannel) key.channel();
                        if (channel.isConnectionPending()) {
                            try {
                                /*
                                 * 人为将程序中止,等待连接创建完成,否则会报如下错误
                                 * java.nio.channels.NotYetConnectedException at sun.nio.ch.SocketChannelImpl.ensureWriteOpen(SocketChannelImpl.java:274)
                                 */
                                if (channel.finishConnect()) {
                                    System.out.println(key.attachment()+" connect server succ");
                                    isConnected = true;
                                }
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    } else if (key.isReadable()) {
                        System.out.println(key.attachment()+ " read ");

                        SocketChannel clientChannel = (SocketChannel) key.channel();

                        try {
                            int len = clientChannel.read(readBuffer);
                            if (len == -1) {
                                System.out.println(key.attachment()+" read : len=-1");
                                // 说明连接已经断开
                                selector.close();
                                socketChannel.close();
                            } else {
                                readBuffer.flip();
                                byte[] buffer = new byte[len];
                                readBuffer.get(buffer);
                                readBuffer.clear();
                                System.out.println(key.attachment()+" read : len=" + len + ", str=" + new String(buffer));
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                    } else if (key.isWritable()) {
                        System.out.println(key.attachment()+ " write ");
                        SocketChannel clientChannel = (SocketChannel) key.channel();
                        String str = "hellos";
                        byte[] buffer = str.getBytes();
                        writeBuffer.put(buffer);
                        writeBuffer.flip();
                        try {
                            System.out.println(key.attachment()+ " write : len=" + buffer.length + ", str=" + str);
                            clientChannel.write(writeBuffer);

                            try {
                                Thread.sleep(100);
                            }catch (Exception e){
                                e.printStackTrace();
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        writeBuffer.clear();
                    }
                    keyIterator.remove();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

UnitTest

    @Test
    public void server(){
        Thread server = new Thread(new NIOServer());
        server.start();

        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        Thread client1 = new Thread(new NIOClient("client1"));
        client1.start();

        Thread client2 = new Thread(new NIOClient("client2"));
        client2.start();

        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


        client1.stop();
        client2.stop();

        server.stop();
	}

结果

运行结果

猜你喜欢

转载自blog.csdn.net/weixin_43430036/article/details/83662904
今日推荐