模仿echo命令学习BIO——Java实现

时间:2022-07-25
本文章向大家介绍模仿echo命令学习BIO——Java实现,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

一、BIO模型:同步阻塞IO处理

在程序的开发之中Java里面最小的处理单元就是线程,也就是说每一个线程可以进行IO的处理,在处理之中,该线程无法进行任何的其他操作。 . 多线程是不可能无限制进行创造的,所以需要去考虑堆线程进行有效的个数控制。如果产生的线程过多,那么直接的问题在于,处理性能降低 ,响应的速度变慢。 需要去区分操作系统的内核线程,以及用户线程的区别,所以最好与内核线程有直接联系,需要使用到固定线程池。

举一个生活中的例子,现在烧水,意味着你现在需要一直盯着水壶去看,一直看它已经烧为止,在这之中你什么都干不了。

echo模型

程序部分

首先创建一个BIO的服务端的类

public class BIOEchoServer {
    public static void main(String[] args) throws Exception{
        ServerSocket serverSocket = new ServerSocket(HostInfo.PORT) ;// 设置监听端口
        System.out.println("服务器端已经启动,监听的端口为:" + HostInfo.PORT);
        boolean flag = true ;
        ExecutorService executorService = Executors.newFixedThreadPool(10) ;
        while(flag) {
            Socket client = serverSocket.accept() ;
            executorService.submit(new EchoClientHandler(client)) ;
        }
        executorService.shutdown() ;
        serverSocket.close() ;
    }

    private static class EchoClientHandler implements Runnable {
        private Socket client ; // 每一个客户端都需要启动一个任务(task)来执行。
        private Scanner scanner ;
        private PrintStream out ;
        private boolean flag = true ;   // 循环标记
        public EchoClientHandler(Socket client) {
            this.client = client ; // 保存每一个客户端操作
            try {
                this.scanner = new Scanner(this.client.getInputStream()) ;
                this.scanner.useDelimiter("n") ; // 设置换行符
                this.out = new PrintStream(this.client.getOutputStream()) ;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void run() {
            while(this.flag) {
                if (this.scanner.hasNext()) {   // 现在有数据进行输入
                    String val = this.scanner.next().trim() ; // 去掉多余的空格内容
                    System.out.println("{服务器端}" + val);
                    if("byebye".equalsIgnoreCase(val)) {
                        this.out.println("ByeByeByte...");
                        this.flag = false ;
                    } else {
                        out.println("【ECHO】" + val);
                    }
                }
            }
            this.scanner.close();
            this.out.close();
            try {
                this.client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

其次创建客户端类

public class BIOEchoClient {
    public static void main(String[] args) throws Exception {
        Socket client = new Socket(HostInfo.HOST_NAME,HostInfo.PORT) ;  // 定义连接的主机信息
        Scanner scan = new Scanner(client.getInputStream()) ;   // 获取服务器端的响应数据
        scan.useDelimiter("n") ;
        PrintStream out = new PrintStream(client.getOutputStream()) ; // 向服务器端发送信息内容
        boolean flag = true ; // 交互的标记
        while(flag) {
            String inputData = InputUtil.getString("请输入要发送的内容:").trim() ;
            out.println(inputData); // 把数据发送到服务器端上
            if(scan.hasNext()) {
                String str = scan.next().trim() ;
                System.out.println(str);
            }
            if ("byebye".equalsIgnoreCase(inputData)) {
                flag = false ;
            }
        }
        client.close();
    }
}

工具类

public class InputUtil {
    private static final BufferedReader KEYBOARD_INPUT = new BufferedReader(new InputStreamReader(System.in));

    private InputUtil() {
    }

    /**
     * 实现键盘数据的输入操作 ,可以返回的数据类型为String
     *
     * @param prompt 提示信息
     * @return 输入的数据返回
     */
    public static String getString(String prompt) {
        boolean flag = true; // 数据接收标记
        String str = null;
        while (flag) {
            System.out.print(prompt);
            try {
                str = KEYBOARD_INPUT.readLine(); // 读取一行数据
                if (str == null || "".equals(str)) {
                    System.out.println("数据输入错误 ,该内容不允许为空:");
                } else {
                    flag = false;
                }
            } catch (IOException e) {
                System.out.println("数据输入错误 ,该内容不允许为空:");
            }
        }
        return str;
    }
}
启动服务端&&客户端

测试一下:

使用 telnet测试