• 实现简单BS架构案例



    BS架构简单通俗理解 就是 浏览器–服务器模式,浏览器 充当 我们的客户端。

    简单BS架构实现案例

    基本原理视图

      
    在这里插入图片描述
      

    注:服务器必须给浏览器 响应 HTTP协议 规定的数据格式,否则浏览器不识别 返回的数据

    访问规则

    服务端若要提供访问服务,就必须遵循浏览器的约定规则,也就是协议

      
    在这里插入图片描述
      


    案例要求

    从浏览器中访问服务器

    并立即让服务器响应一个很简单的网页给浏览器

    展示网页内容 就是 “12 ITxie_我的IT之路”


    改造前

    服务端

    package com.xie.net.complete.tcp.group.bs;
    
    import java.net.ServerSocket;
    import java.net.Socket;
    
    /**
     * 目标:完成TCP通信快速入门-服务端开发:要求实现与多个客户端同时进行通信
     * */
    public class Server {
        public static void main(String[] args) throws Exception {
            System.out.println("----------服务端启动成功----------");
            // 创建ServerSocket对象,同时为服务端注册端口号,为后续客户端的请求提供访问位置
            ServerSocket serverSocket = new ServerSocket(8080);
            while(true) {
                // 使用ServerSocket对象,调用accent方法,阻塞等待客户端的连接
                Socket socket = serverSocket.accept();
                System.out.println("有人上线了:" + socket.getRemoteSocketAddress());
                // 新建线程,把此客户端(这里指浏览器)的 通信管道socket,交给 一个独立的线程 负责处理业务
                new ServerReaderThread(socket).start();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    线程模版类

    package com.xie.net.complete.tcp.group.bs;
    
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.PrintStream;
    import java.net.Socket;
    public class ServerReaderThread extends Thread {
        private Socket socket;
        public ServerReaderThread(Socket socket) {
            this.socket = socket;
        }
    
        @Override
        public void run() {
            /**
             * 立即响应一个网页内容:”12 ITxie_我的IT之路“给浏览器渲染(包括html标签的渲染),然后展示给用户观看
             * */
            try (
                    OutputStream os = socket.getOutputStream();
                    PrintStream ps = new PrintStream(os)
                    ){
                ps.println("HTTP/1.1 200 OK");
                ps.println("Content-Type: text/html;charset=UTF-8");
                // 换行
                ps.println();
                ps.println("
    12 ITxie_我的IT之路
    "
    ); socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    改造后(优化)

    优化策略

      
    在这里插入图片描述
      

    服务端

    package com.xie.net.complete.tcp.group.bs.modify;
    
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.concurrent.ArrayBlockingQueue;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    
    /**
     * 目标:完成TCP通信快速入门-服务端开发:要求实现与多个客户端同时进行通信。
     *
     * 优化前面代码,使用线程池解决,其中涉及到了资源合理回收利用问题
     * 解决高并发问题:
     * 改造用线程池来提供服务,缓解短时间内大量访问请求可能导致性能瓶颈,然后系统宕机的问题
     * (引起原因:系统性能跟不上,忙不过来,每产生一个新线程都是会消耗系统资源的,而资源总归有限)
     * */
    public class Server {
        public static void main(String[] args) throws Exception {
            System.out.println("----------服务端启动成功----------");
            // 创建ServerSocket对象,同时为服务端注册端口号,为客户端后续的请求提供访问位置
            ServerSocket serverSocket = new ServerSocket(8080);
    
            /**
             * 创建线程池,其各参数具体含义:
             * 参数一:核心线程数量
             * 参数二:最大线程数量
             * 参数三:临时线程存活时间
             * 参数四:参数三的时间单位
             * 参数五:任务队列,此处用于 缓存 来自通信管道的任务的
             * 参数六:线程工厂,用于创建核心线程的
             * 参数七:任务的拒绝策略,此处用到默认策略,直接拒绝的处理方案,当处理不了时,直接抛异常
             * */
            // 创建出一个线程池,负责处理通信管道的任务
            ThreadPoolExecutor pool = new ThreadPoolExecutor(16 * 2, 16 * 2, 0,
                    TimeUnit.SECONDS, new ArrayBlockingQueue<>(8),
                    Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
    
            while(true) {
                // 使用ServerSocket对象,调用accent方法,阻塞等待客户端的连接
                Socket socket = serverSocket.accept();
                System.out.println("有人上线了:" + socket.getRemoteSocketAddress());
                /**
                 * 把通信管道 交给 任务对象 然后 传递给 线程池对象处理。
                 * 其实,此客户端的 通信管道socket最终也是交给 一个独立的线程 负责处理业务。
                 * 只不过 此线程 处理完任务后 立即被回收 以待复用。
                 */
                pool.execute(new ServerReaderRunable(socket));
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    线程模版类

    package com.xie.net.complete.tcp.group.bs.modify;
    
    import java.io.OutputStream;
    import java.io.PrintStream;
    import java.net.Socket;
    
    /**
     * 包装Socket通信管道的 任务对象模版类,其中 定义 需要处理的任务
     * */
    public class ServerReaderRunable implements Runnable {
        private Socket socket;
        public ServerReaderRunable(Socket socket) {
            this.socket = socket;
        }
    
        @Override
        public void run() {
            /**
             * 立即响应一个网页内容:”12 ITxie_我的IT之路“给浏览器渲染(包括html标签的渲染),然后展示给用户观看
             * */
            try (
                    OutputStream os = socket.getOutputStream();
                    PrintStream ps = new PrintStream(os)
                    ){
                ps.println("HTTP/1.1 200 OK");
                ps.println("Content-Type: text/html;charset=UTF-8");
                ps.println();
                ps.println("
    12 ITxie_我的IT之路
    "
    ); socket.close(); } catch (Exception e) { e.printStackTrace(); } } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    参考视频

    黑马磊哥

  • 相关阅读:
    华为机试_HJ22 汽水瓶【简单】【半收藏】
    AI创作与大语言模型:2023亚马逊云科技中国峰会引领企业应用新潮流
    持续进化,快速转录,Faster-Whisper对视频进行双语字幕转录实践(Python3.10)
    curl认证过期
    NPM 与 XUI 共存!Nginx Proxy Manager 搭配 X-UI 实现 Vless+WS+TLS 教程!
    PDF怎么在手机上删除不要的页
    使用Jest搭建自动化单元测试框架为Vue 3项目
    国联易安:网络反不正当竞争,要防患于未然
    Spring中bean的生命周期
    Makefile与CMake学习笔记
  • 原文地址:https://blog.csdn.net/m0_69604107/article/details/133501022