zoukankan      html  css  js  c++  java
  • BIO

    Netty 是一个利用 Java 的高级网络的能力,隐藏了Java背后的复杂性然后提供了一个易于使用的 API 的客户端/服务器框架。

    • 高性能

    • 扩展性强

    • 在网络发展初期,需要花很多时间来学习 socket 的复杂,寻址等等,在 C socket 库上进行编码,并需要在不同的操作系统上做不同的处理。

    • Java 早期版本(1995-2002)介绍了足够的面向对象的糖衣来隐藏一些复杂性,但实现复杂的客户端-服务器协议仍然需要大量的样板代码(和进行大量的监视才能确保他们是对的)。

    BIO

    public static void main(String[] args) throws Exception {
        //1.ServerSocket 创建并监听端口的连接请求
        ServerSocket serverSocket = new ServerSocket(888);
        //2.accept() 调用阻塞,直到一个连接被建立了。返回一个新的 Socket 用来处理 客户端和服务端的交互
        Socket clientSocket = serverSocket.accept();
        //3.流被创建用于处理 socket 的输入和输出数据。BufferedReader 读取从字符输入流里面的文本。PrintWriter 打印格式化展示的对象读到本文输出流
        InputStream inputStream = clientSocket.getInputStream();
        OutputStream outputStream = clientSocket.getOutputStream();
        //4.处理循环开始 readLine() 阻塞,读取字符串直到最后是换行或者输入终止。
        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
        PrintWriter pw = new PrintWriter(outputStream);
        //5.如果客户端发送的是“Done”处理循环退出
        String request,response;
        while ((request = br.readLine()) != null){
            if("Done".equals(request)){
                break;
            }
            //6.执行方法处理请求,返回服务器的响应
            response = "服务器收到消息:" + request;
            //7.响应发回客户端
            pw.println(response);
        }//8.处理循环继续
    
    }
    

    这段代码限制每次只能处理一个连接。为了实现多个并行的客户端我们需要分配一个新的 Thread 给每个新的客户端 Socket(当然需要更多的代码)。但考虑使用这种方法来支持大量的同步,长连接。在任何时间点多线程可能处于休眠状态,等待输入或输出数据。这很容易使得资源的大量浪费,对性能产生负面影响

    BIO实现多人聊天

    原生 socket 库同时也包含了非阻塞 I/O 的功能。这使我们能够确定任何一个 socket 中是否有数据准备读或写。我们还可以设置标志,因为读/写调用如果没有数据立即返回;就是说,如果一个阻塞被调用后就会一直阻塞,直到处理完成。

    • serverSocket.accept(); 会等待一个新的socket客户端连接

    • BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));

      br.readLine() 这里会等待客户端或者服务端响应消息

    阻塞的同时需要处理其他的业务,那么就需要开启新的线程去处理业务

    服务端

    public class MyServerSocket {
        //连接的客户端
        private static Set<Socket> socketSet = new HashSet<>();
    
        public static void main(String[] args) throws Exception {
            ServerSocket serverSocket = new ServerSocket(889);
            int index = 0;
            while(true){
                index ++ ;
                //这里会阻塞住,
                Socket socket = serverSocket.accept();
                socketSet.add(socket);
    
                //对每个socket的输入都开启一个线程进行监听
                new Thread(() ->{
                    try{
                        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        //监听客户端的请求参数
                        while(true){
                            try{
                                String message = bufferedReader.readLine();
                                System.out.println(Thread.currentThread().getName() + ":" + message);
                                //遍历客户端,将其中一个客户端的消息发送给其他客户端
                                for (Socket socket1 : socketSet) {
                                    if(!socket1.equals(socket)){
                                        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket1.getOutputStream()));
                                        bufferedWriter.write(Thread.currentThread().getName() + ":" + message + "\n");
                                        bufferedWriter.flush();
                                    }
                                }
                            }catch (Exception e){
                                System.out.println( Thread.currentThread().getName() + "可能退出了,将它移除掉");
                                socketSet.remove(socket);
                                break;
                            }
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                },"用户" + index).start();
            }
        }
    }
    

    客户端

    public class MyClientSocket {
        public static void main(String[] args) throws Exception {
    
            Socket socket = new Socket("127.0.0.1",889);
            new Thread(()->{
                try {
                    //等待接受服务端的消息
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    while(true){
                        String s = bufferedReader.readLine();
                        System.out.println( s);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            //一直等待客户端的输入
            while(true){
                BufferedReader systemIn = new BufferedReader(new InputStreamReader(System.in));
                String readLine = systemIn.readLine();
                bw.write( readLine+ "\n");
                bw.flush();
            }
        }
    }
    
  • 相关阅读:
    聊聊关于性能优化和其他(一)
    JavaScript 事件循环及异步原理(完全指北)
    SPA路由机制详解(看不懂不要钱~~)
    Web安全系列(三):XSS 攻击进阶(挖掘漏洞)
    Web安全系列(二):XSS 攻击进阶(初探 XSS Payload)
    浅谈Generator和Promise原理及实现
    Kubernetes 服务目录
    Kubernetes 网络模型
    个人开源贡献记录
    【转载】DTO – 服务实现中的核心数据
  • 原文地址:https://www.cnblogs.com/steven158/p/15057258.html
Copyright © 2011-2022 走看看