使用NIO实现一个echo服务器

    一个简单的echo服务器,客户端向服务端发送消息,服务端进行响应,当客户端发送quit字符串时,断开客户端和服务端的连接。使用NIO实现

    服务端代码

public class EchoServer_NIO {
    private Selector selector;
    private ByteBuffer sendBuf = ByteBuffer.allocate(1024);
    private ByteBuffer recBuf = ByteBuffer.allocate(1024);
    public EchoServer_NIO(){
        try {
            System.out.println("服务器正在启动");
            selector = Selector.open();
            ServerSocketChannel ssc = ServerSocketChannel.open();
            //设置非阻塞模式
            ssc.configureBlocking(false);
            //绑定端口
            ssc.bind(new InetSocketAddress(8777));
            ssc.register(selector, SelectionKey.OP_ACCEPT);
            System.out.println("服务器启动成功");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("服务器启动失败");
        }
    }

    public static void main(String[] args) {
        new EchoServer_NIO().service();
    }

    public void service(){
        while (true){
            try {
                int select = selector.select();
                if (select>0){
                    Set<SelectionKey> selectionKeys = selector.selectedKeys();
                    Iterator<SelectionKey> iterator = selectionKeys.iterator();
                    while (iterator.hasNext()){
                        SelectionKey key = iterator.next();
                        iterator.remove();
                        //如果是有效的
                        if (key.isValid()){
                            if (key.isAcceptable()){
                                accept(key);
                            }else if(key.isReadable()){
                                read(key);
                            }else if(key.isWritable()){
                                write(key);
                            }
                        }
                    }
                    selectionKeys.clear();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void accept(SelectionKey key){
        try {
            ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
            SocketChannel sc = ssc.accept();
            sc.configureBlocking(false);
            sc.register(selector,SelectionKey.OP_READ);
        }catch (Exception e){
            e.printStackTrace();
        }

    }
    private void read(SelectionKey key) {
        try {
            recBuf.clear();
            SocketChannel sc = (SocketChannel) key.channel();
            int read = sc.read(recBuf);
            if (read<0){
                key.channel().close();
                key.cancel();
                return;
            }
            recBuf.flip();
            String recText = new String(recBuf.array(),0,read);
            System.out.println(recText);
            if (recText.equals("quit")){
                sendBuf.clear();
                sendBuf.put("bye".getBytes());
                sc.write(sendBuf);
                key.channel().close();
                key.cancel();
                return;
            }
            sc.register(selector,SelectionKey.OP_WRITE);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    private void write(SelectionKey key) {
        try {
            SocketChannel sc = (SocketChannel) key.channel();
            sendBuf.clear();
            String sendText = "hello";
            sendBuf.put(sendText.getBytes());
            sendBuf.flip();
            sc.write(sendBuf);
            sc.register(selector,SelectionKey.OP_READ);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

    客户端代码

public class EchoClient_NIO {
    private Selector selector;
    
    private ByteBuffer sendBuf = ByteBuffer.allocate(1024);
    
    private ByteBuffer revBuf = ByteBuffer.allocate(1024);
    
    public EchoClient_NIO(){
        try {
            System.out.println("正在连接服务器...");
            SocketChannel socketChannel = SocketChannel.open();
            socketChannel.configureBlocking(false);
            selector = Selector.open();
            socketChannel.register(selector, SelectionKey.OP_CONNECT);
            socketChannel.connect(new InetSocketAddress("localhost",8777));
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public void service() throws IOException {
        while (true){
                    selector.select();
                    Set<SelectionKey> keys = selector.selectedKeys();
                    Iterator<SelectionKey> iterator = keys.iterator();
                    while (iterator.hasNext()){
                        SelectionKey key = iterator.next();
                        iterator.remove();
                        if (key.isConnectable()){
                            connect(key);
                        }else if (key.isReadable()){
                            read(key);
                        }else if (key.isWritable()){
                            write(key);
                        }
                    keys.clear();
                }
        }
    }

    private void connect(SelectionKey key) {
        try {
            SocketChannel sc = (SocketChannel) key.channel();
            if (sc.isConnectionPending()){
                sc.finishConnect();
                System.out.println("服务器连接成功");
                sc.register(selector,SelectionKey.OP_WRITE);
            }
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("服务器连接失败");
        }
    }
    private void read(SelectionKey key) {
        try {
            revBuf.clear();
            SocketChannel sc = (SocketChannel) key.channel();
            int read = sc.read(revBuf);
            if (read>0) {
                revBuf.flip();
                String recText = new String(revBuf.array(), 0, read);
                System.out.println(recText);
                if (recText.equals("quit")) {
                    key.channel().close();
                    key.cancel();
                    return;
                }
                sc.register(selector, SelectionKey.OP_WRITE);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    private void write(SelectionKey key) {
        try {
            sendBuf.clear();
            SocketChannel sc = (SocketChannel) key.channel();
            Scanner scanner = new Scanner(System.in);
            String message = scanner.nextLine();
            sendBuf.put(message.getBytes());
            sendBuf.flip();
            sc.write(sendBuf);
            if (message.equals("quit")){
                key.channel().close();
                key.cancel();
                selector.close();
                return;
            }
            sc.register(selector,SelectionKey.OP_READ);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException {
        new EchoClient_NIO().service();
    }
}
    NIO不易使用,使用时需谨慎

猜你喜欢

转载自blog.csdn.net/yanghan1222/article/details/80464942