实现简单BS架构案例

news2025/1/12 20:55:40

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();
        }
    }
}

线程模版类

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("<div style='color:red;font-size:120px;text-align:center'>12 ITxie_我的IT之路</div>");
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

改造后(优化)

优化策略

  
在这里插入图片描述
  

服务端

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));
        }
    }
}

线程模版类

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("<div style='color:red;font-size:120px;text-align:center'>12 ITxie_我的IT之路</div>");
            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

参考视频

黑马磊哥

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1056789.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【VsCode】SSH远程连接Linux服务器开发,搭配cpolar内网穿透实现公网访问

文章目录 前言1、安装OpenSSH2、vscode配置ssh3. 局域网测试连接远程服务器4. 公网远程连接4.1 ubuntu安装cpolar内网穿透4.2 创建隧道映射4.3 测试公网远程连接 5. 配置固定TCP端口地址5.1 保留一个固定TCP端口地址5.2 配置固定TCP端口地址5.3 测试固定公网地址远程 前言 远程…

奥斯卡·王尔德

奥斯卡王尔德 奥斯卡王尔德&#xff08;Oscar Wilde&#xff0c;1854年10月16日—1900年11月30日&#xff09;&#xff0c;出生于爱尔兰都柏林&#xff0c;19世纪英国&#xff08;准确来讲是爱尔兰&#xff0c;但是当时由英国统治&#xff09;最伟大的作家与艺术家之一&#xf…

【Java 进阶篇】JDBC ResultSet 遍历结果集详解

在Java数据库编程中&#xff0c;经常需要执行SQL查询并处理查询结果。ResultSet&#xff08;结果集&#xff09;是Java JDBC中用于表示查询结果的关键类之一。通过遍历ResultSet&#xff0c;我们可以访问和操作从数据库中检索的数据。本文将详细介绍如何使用JDBC来遍历ResultSe…

手把手教你做个智能加湿器(一)

一、前言 目前常见的加湿器类电子产品一般是由PCBA和外壳组成&#xff0c;我们将从PCB设计&#xff0c;然后编写软件&#xff0c;接着设计外壳&#xff0c;设计出一个完整的产品出来。 需要使用到软件&#xff1a; Altium Designer 17 SolidWorks 2019 Keil 4 二…

C++--位图和布隆过滤器

1.什么是位图 所谓位图&#xff0c;就是用每一位来存放某种状态&#xff0c;适用于海量数据&#xff0c;数据无重复的场景。通常是用来判断某个数据存不存在的。比如int 有32位&#xff0c;就可以存放0到31这32个数字在不在某个文件中。当然&#xff0c;其他类型也可以。 2.位…

Python|OpenCV-如何给目标图像添加边框(7)

前言 本文是该专栏的第7篇,后面将持续分享OpenCV计算机视觉的干货知识,记得关注。 在使用opencv处理图像的时候,会不可避免的对图像的一些具体区域进行一些操作。比如说,想要给目标图像创建一个围绕图像的边框。简单的来说,就是在图片的周围再填充一个粗线框。具体效果,…

真红之刃攻略,真红之刃氪金攻略

真红之刃新手怎么玩&#xff1f;这款游戏有很多值得新手们了解的内容。下面我们来详细了解一下游戏的玩法。 关注【娱乐天梯】&#xff0c;获取真红之刃0.1折内部福利号 1、恶魔广场&#xff1a;这是奇迹中最受欢迎的玩法之一&#xff0c;也是每日必刷的副本之一。进入条件是1转…

(Note)机器学习面试题

机器学习 1.两位同事从上海出发前往深圳出差&#xff0c;他们在不同时间出发&#xff0c;搭乘的交通工具也不同&#xff0c;能准确描述两者“上海到深圳”距离差别的是&#xff1a; A.欧式距离 B.余弦距离 C.曼哈顿距离 D.切比雪夫距离 S:D 1. 欧几里得距离 计算公式&#x…

经典算法-----迷宫问题(栈的应用)

目录 前言 迷宫问题 算法思路 1.栈的使用方法 ​编辑2.方向的定义 代码实现 栈的cpp代码&#xff1a; 栈的头文件h代码: 走迷宫代码&#xff1a; 前言 今天学习一种算法问题&#xff0c;也就是我们常见的迷宫问题&#xff0c;本期我们通过前面学习过的数据结构---栈来…

一种基于体素的射线检测

效果 基于体素的射线检测 一个漏检的射线检测 从起点一直递增指定步长即可得到一个稀疏的检测 bool Raycast(Vector3 from, Vector3 forword, float maxDistance){int loop 6666;Vector3 pos from;Debug.DrawLine(from, from forword * maxDistance, Color.red);while (loo…

Vue3切换路由白屏刷新后才显示页面内容

问题所在&#xff1a; 1.首先检查页面路由以及页面路径配置是否配置错误。 2.如果页面刷新可以出来那证明不是配置的问题&#xff0c;其次检查是否在根组件标签最外层包含了个最大的div盒子包裹内容。&#xff08;一般vue3是可以不使用div盒子包裹的&#xff09; 3.最后如果…

快速开发微信小程序之一登录认证

一、背景 记得11、12年的时候大家一窝蜂的开始做客户端Android、IOS开发&#xff0c;我是14年才开始做Andoird开发&#xff0c;干了两年多&#xff0c;然后18年左右微信小程序火了&#xff0c;我也做了两个小程序&#xff0c;一个是将原有牛奶公众号的功能迁移到小程序&#x…

【iptables 实战】04 高级用法:iptables模块之state扩展

一、场景描述 假设我们内部的主机&#xff0c;想访问新闻网站&#xff0c;即访问其80端口。要想正确地获取到http报文内容。我们对这个网络报文应该这么设置 出去的报文&#xff0c;目标端口&#xff0c;80端口&#xff0c;放行进入的报文&#xff0c;源端口&#xff0c;80端…

vertx的学习总结2

一、什么是verticle verticle是vertx的基本单元&#xff0c;其作用就是封装用于处理事件的技术功能单元 &#xff08;如果不能理解&#xff0c;到后面的实战就可以理解了&#xff09; 二、写一个verticle 1. 引入依赖&#xff08;这里用的是gradle&#xff0c;不会吧&#…

几个推荐程序员养成的好习惯

本文框架 前言case1 不想当然case2 不为了解决问题而解决问题case3 不留问题死角case4 重视测试环节 前言 中秋国庆双节至&#xff0c;旅行or回乡探亲基本是大家的选择&#xff0c;看看风景或陪陪家人确实是个难得的机会。不过我的这次假期选择了闭关&#xff0c;不探亲&#…

手机号码(作为查询参数)格式校验:@PhoneQuery(自定义参数校验注解)

目标 自定义一个用于校验&#xff08;作为查询参数的&#xff09;手机号码格式的注解PhoneQuery&#xff0c;能够和现有的 Validation 兼容&#xff0c;使用方式和其他校验注解保持一致。 校验逻辑 可以为 null 或 空字符串&#xff1b;不能包含空格&#xff1b;必须为数字序…

开放式耳机哪个好、百元开放式耳机推荐品牌

开放式耳机以其独特的设计和出色的性能优势&#xff0c;成为许多音乐爱好者的首选。与传统的入耳式耳机相比&#xff0c;开放式耳机给用户带来更加舒适的佩戴体验。无需插入耳道&#xff0c;避免了长时间佩戴带来的不适感&#xff0c;让你可以尽情享受音乐而不受干扰。此外&…

Codeforces Round 901 (Div. 1) B. Jellyfish and Math(思维题/bfs)

题目 t(t<1e5)组样例&#xff0c;每次给出a,b,c,d,m(0<a,b,c,d,m<2的30次方) 初始时&#xff0c;(x,y)(a,b)&#xff0c;每次操作&#xff0c;你可以执行以下四种操作之一 ①xx&y&#xff0c;&为与 ②xx|y&#xff0c;|为或 ③yx^y&#xff0c;^为异或 …

心连心,同一个地方,同一个程序员

Hi,all, 现在开始所有一线城市和二线城市建立程序员交流群,为了防止病毒以及一些丧心病狂的广告人士,现在各大群以程序员为基础,入群者必须为程序员,严谨广告和僵尸人士入群,有想加群者加我微信,备注城市。比如想加入南京程序员交流群,备注南京,或者微信聊天窗口私聊…

基于 QT 实现一个 Ikun 专属桌面宠物

Step0、实现思路 想到的思路有两种&#xff1a; 1、使用 QT 的状态机模式&#xff0c;参考官网文档&#xff0c;这个模式的解耦最佳 2、使用原生 Wigets&#xff0c;将窗口设置为透明无框&#xff0c;循环播放桌面宠物的状态 本文采用第二种思路&#xff0c;实现一个极简版…