网络通信协议
WebSocket通信
- WebSocket是一种基于TCP的网络通信协议,提供了浏览器和服务器之间的全双工通信(full-duplex)能力。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。这使得数据可以更快地从服务器传到浏览器,而且减少了数据传输的数据量,因为头信息比较小。在WebSocket API中,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
- HTTP协议和WebSocket协议的主要区别如下:
- 连接方式:HTTP协议是无短连接的。每次请求都需要建立新的连接,请求结束后连接就断开。而WebSocket协议是长连接的,客户端和服务器建立连接后,直到其中一方主动断开,连接才会断开。
- 数据传输:HTTP协议只能由客户端向服务器发起请求,服务器返回响应数据。而WebSocket协议是全双工通信,服务器和客户端都可以主动发送数据。
- 性能开销:由于HTTP协议每次请求都需要建立新的连接,所以开销较大。而WebSocket协议建立连接后,可以进行多次数据传输,开销较小。
- 数据格式:HTTP协议传输的数据格式比较复杂,包含了请求行、请求头、消息体等。而WebSocket协议传输的数据通过帧来传输,数据格式比较简单。
- 实时性:HTTP协议的实时性不强,需要客户端定时轮询服务器获取新的数据。而WebSocket协议可以实现服务器主动推送数据,实时性较强。
- WebSocket主要适用于以下几种场景:
- 实时应用:聊天应用、多人协作应用、在线游戏、实时购物等。
- 实时数据推送:股票、新闻、天气、设备状态等实时信息的推送。
- IOT物联网:实时获取设备状态,实时控制设备等。
- 实时分析:实时数据分析、实时监控系统等。
WebSocket入门案例
-
客户端:
- 创建WebSocket对象:在JavaScript中,我们可以创建一个WebSocket对象,指定要连接的服务器地址。
var ws = new WebSocket("ws://localhost:8080/websocket");
- 监听事件:WebSocket对象提供了四个事件:onopen、onmessage、onerror、onclose,我们可以通过监听这些事件来处理WebSocket的各种情况。
ws.onopen = function(event) {console.log("Connection open ..."); };ws.onmessage = function(event) {console.log("Received Message: " + event.data); };ws.onclose = function(event) {console.log("Connection closed ..."); };ws.onerror = function(event) {console.log("Error: " + event.data); };
- 发送数据:WebSocket对象提供了一个send方法,我们可以通过这个方法向服务器发送数据。
ws.send("Hello Server!");
- 关闭连接:当我们不再需要WebSocket连接时,可以调用WebSocket对象的close方法来关闭连接。
ws.close();
可以直接使用js写个小页面
<!DOCTYPE HTML> <html> <head><meta charset="UTF-8"><title>WebSocket Demo</title> </head> <body><input id="text" type="text" /><button onclick="send()">Send Message</button><button onclick="closeWebSocket()">Close</button><div id="message"></div> </body> <script type="text/javascript">var websocket = null;var clientId = Math.random().toString(36).substr(2);//判断当前浏览器是否支持WebSocketif('WebSocket' in window){//连接WebSocket节点websocket = new WebSocket("ws://localhost:8080/ws/"+clientId);}else{alert('Not support websocket')}//连接发生错误的回调方法websocket.onerror = function(){setMessageInnerHTML("error");};//连接成功建立的回调方法websocket.onopen = function(){setMessageInnerHTML("连接成功");}//接收到消息的回调方法websocket.onmessage = function(event){setMessageInnerHTML(event.data);}//连接关闭的回调方法websocket.onclose = function(){setMessageInnerHTML("close");}//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。window.onbeforeunload = function(){websocket.close();}//将消息显示在网页上function setMessageInnerHTML(innerHTML){document.getElementById('message').innerHTML += innerHTML + '<br/>';}//发送消息function send(){var message = document.getElementById('text').value;websocket.send(message);}//关闭连接function closeWebSocket() {websocket.close();} </script> </html>
-
服务端:
-
导入WebSocket的maven坐标
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dependency>
-
导入WebSocket服务端组件WebSocketServer,用于与客户端通信
package com.sky.websocket;import com.sky.handler.TurnoverReportVOEncoder; import org.springframework.stereotype.Component; import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.util.Collection; import java.util.HashMap; import java.util.Map;/*** WebSocket服务*/ @Component @ServerEndpoint(value = "/ws/{sid}",encoders = {TurnoverReportVOEncoder.class}) // 为对象指定编码器(目前是转成json发送给客户端) public class WebSocketServer {//存放会话对象private static Map<String, Session> sessionMap = new HashMap();/*** 连接建立成功调用的方法*/@OnOpenpublic void onOpen(Session session, @PathParam("sid") String sid) {System.out.println("客户端:" + sid + "建立连接");sessionMap.put(sid, session);}/*** 收到客户端消息后调用的方法** @param message 客户端发送过来的消息*/@OnMessagepublic void onMessage(String message, @PathParam("sid") String sid) {System.out.println("收到来自客户端:" + sid + "的信息:" + message);}/*** 连接关闭调用的方法** @param sid*/@OnClosepublic void onClose(@PathParam("sid") String sid) {System.out.println("连接断开:" + sid);sessionMap.remove(sid);}/*** 群发** @param message*/public void sendToAllClient(String message) {Collection<Session> sessions = sessionMap.values();for (Session session : sessions) {try {//服务器向客户端发送消息session.getBasicRemote().sendText(message);} catch (Exception e) {e.printStackTrace();}}}public void sendObjToAllClient(Object object) {Collection<Session> sessions = sessionMap.values();for (Session session : sessions) {try {//服务器向客户端发送对象--注意第4步骤,需要为该对象指定一个编码器session.getBasicRemote().sendObject(object);} catch (Exception e) {e.printStackTrace();}}}}
-
导入配置类WebSocketConfiguration,注册WebSocket的服务端组件ServerEndpointExporter
package com.sky.config;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter;/*** WebSocket配置类,用于注册WebSocket的Bean*/ @Configuration public class WebSocketConfiguration {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();} }
-
如果想向客户端推送封装好的对象,在WebSocket中,需要提供一个编码器来将这个对象转换为可以通过网络传输的格式,通常是字符串或者二进制数据。
package com.sky.handler;import com.fasterxml.jackson.databind.ObjectMapper; import com.sky.vo.TurnoverReportVO;import javax.websocket.EncodeException; import javax.websocket.Encoder; import javax.websocket.EndpointConfig;/*** @projectName: sky-take-out* @package: com.sky.handler* @className: TurnoverReportVOEncoder* @author: fangjiayueyuan* @description: TODO* @date: 2023/12/24 16:16* @version: 1.0*/ public class TurnoverReportVOEncoder implements Encoder.Text<TurnoverReportVO>{private static ObjectMapper objectMapper = new ObjectMapper();@Overridepublic String encode(TurnoverReportVO turnoverReportVO) throws EncodeException {try {// 使用Jackson库将对象转换为JSON字符串return objectMapper.writeValueAsString(turnoverReportVO);} catch (Exception e) {throw new EncodeException(turnoverReportVO, "对象转换为JSON字符串时发生错误", e);}}@Overridepublic void init(EndpointConfig endpointConfig) {// 这里可以进行编码器的初始化操作,但在这个例子中我们不需要进行任何操作}@Overridepublic void destroy() {// 这里可以进行编码器的清理操作,但在这个例子中我们不需要进行任何操作} }
-
导入定时任务类WebSocketTask,定时向客户端推送数据
package com.sky.task;import com.sky.service.ReportService; import com.sky.vo.TurnoverReportVO; import com.sky.websocket.WebSocketServer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component;import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter;@Component public class WebSocketTask {@Autowiredprivate WebSocketServer webSocketServer;@Autowiredprivate ReportService reportService;/*** 通过WebSocket每隔5秒向客户端发送消息*/@Scheduled(cron = "0/5 * * * * ?")public void sendMessageToClient() {webSocketServer.sendToAllClient("这是来自服务端的消息:" + DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now()));}/*** 通过WebSocket每隔5秒向客户端发送消息*/@Scheduled(cron = "0/5 * * * * ?")public void sendObjMessageToClient() {TurnoverReportVO turnoverStatistics = reportService.getTurnoverStatistics(LocalDate.parse("2023-01-01"), LocalDate.now());webSocketServer.sendToAllClient("传个对象过去");webSocketServer.sendObjToAllClient(turnoverStatistics);} }
-
RPC通信
**RPC(Remote Procedure Call)**是一种通信协议,它允许运行在一台计算机上的程序调用另一台计算机上的程序中的函数或方法,就像调用本地函数一样,无需程序员显式处理底层的网络细节。
RPC的主要特征包括:
-
透明性:对于调用者来说,远程过程调用和本地过程调用是透明的,调用者无需关心过程调用的是本地过程还是远程过程。
-
语言无关性:RPC通常支持多种编程语言,只要两个通信的程序遵循同一RPC协议,它们就可以进行通信,无论它们是用什么编程语言编写的。
-
同步性:RPC通常是同步的,也就是说,当一个RPC调用发出后,调用者会停止执行,直到得到结果。然而,也有一些RPC系统支持异步调用。
为什么使用RPC:
-
简化分布式系统的开发:RPC隐藏了底层的网络通信和数据传输的复杂性,使得开发分布式应用更加简单。
-
提高代码的可重用性:通过RPC,可以将一些通用的功能实现为服务,然后在多个应用中重用这些服务。
-
提高系统的可扩展性:通过RPC,可以将一个大的系统分解为多个可以独立开发和部署的小的服务。
RPC的替代方案:
- RESTful API:RESTful API是一种基于HTTP协议的通信方式,它使用HTTP的方法(如GET、POST、PUT、DELETE等)来操作资源。RESTful API比RPC更简单,更易于使用,但它不如RPC灵活,因为它只能使用HTTP协议,而RPC可以使用任何传输协议。
- 消息队列:消息队列是一种异步的通信方式,它允许程序通过发送和接收消息来进行通信。消息队列可以解耦发送者和接收者,使得它们可以独立地扩展和失败。然而,消息队列的使用比RPC更复杂,因为它需要处理消息的发送、接收、存储和确认。
RPC入门案例
以Thrift为例:
-
定义数据类型和服务接口:使用Thrift的IDL(接口定义语言)定义数据类型和服务接口,然后通过Thrift的编译器生成对应语言的代码。
namespace java com.sankuai.mdp.thriftstruct User{1:i32 id2:string name3:i32 age=0 }service UserService{User getById(1:i32 id)bool isExist(1:string name) }
-
通过Thrift编译器生成Java代码:会生成两个对象:User、UserService
thrift --gen java HelloWorld.thrift
-
服务端代码,实现UserService.Iface接口;启动服务端.
package com.sankuai.mdp.thriftserversnapshot.service.impl;import com.sankuai.mdp.thriftapisnapshot.entity.User; import com.sankuai.mdp.thriftapisnapshot.entity.UserService; import org.apache.thrift.TException;/*** @projectName: thrift-api-snapshot* @package: com.sankuai.mdp.thriftserversnapshot.service.impl* @className: UserServiceImpl* @author: fangjiayueyuan* @description: TODO* @date: 2023/12/17 21:33* @version: 1.0*/ public class UserServiceImpl implements UserService.Iface{@Overridepublic User getById(int id) throws TException {System.out.println("-----调用getById-----");User user = new User();user.setId(id);user.setName("dog");user.setAge(18);return user;}@Overridepublic boolean isExist(String name) throws TException {return false;} }
package com.sankuai.mdp.thriftserversnapshot.service.impl;import com.sankuai.mdp.thriftapisnapshot.entity.UserService; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.server.TServer; import org.apache.thrift.server.TSimpleServer; import org.apache.thrift.transport.TServerSocket; import org.apache.thrift.transport.TServerTransport; import org.apache.thrift.transport.TTransportException;/*** @projectName: thrift-api-snapshot* @package: com.sankuai.mdp.thriftserversnapshot.service.impl* @className: SimpleService* @author: fangjiayueyuan* @description: TODO* @date: 2023/12/17 21:59* @version: 1.0*/ public class SimpleService {public static void main(String[] args) {try{TServerTransport serverTransport = new TServerSocket(9090);UserService.Processor processor = new UserService.Processor(new UserServiceImpl());TBinaryProtocol.Factory protocolFactory = new TBinaryProtocol.Factory();TSimpleServer.Args targs = new TSimpleServer.Args(serverTransport);targs.processor(processor);targs.protocolFactory(protocolFactory);TServer server = new TSimpleServer(targs);server.serve();} catch (TTransportException e) {throw new RuntimeException(e);}} }
-
客户端代码,调用服务端的方法,就像调用本地方法一样
package com.sankuai.mdp.thriftclientsnapshot.service.impl;import com.sankuai.mdp.thriftapisnapshot.entity.User; import com.sankuai.mdp.thriftapisnapshot.entity.UserService; import org.apache.thrift.TException; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.transport.TSocket; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException;/*** @projectName: thrift-api-snapshot* @package: com.sankuai.mdp.thriftclientsnapshot.service.impl* @className: SimpleClient* @author: fangjiayueyuan* @description: TODO* @date: 2023/12/17 21:58* @version: 1.0*/ public class SimpleClient {public static void main(String[] args) {TTransport transport = null;try {transport = new TSocket("localhost", 9090);TBinaryProtocol protocol = new TBinaryProtocol(transport);UserService.Client client = new UserService.Client(protocol);transport.open();User result = client.getById(1);System.out.println("Result:" + result);} catch (TTransportException e) {e.printStackTrace();} catch (TException e) {throw new RuntimeException(e);} finally {if (transport != null) {transport.close();}}} }
-
先后启动运行服务端SimpleService.java、客户端代码SimpleClient.java
Git
相关文章:

网络通信协议
WebSocket通信 WebSocket是一种基于TCP的网络通信协议,提供了浏览器和服务器之间的全双工通信(full-duplex)能力。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接ÿ…...

Spark集群部署与架构
在大数据时代,处理海量数据需要分布式计算框架。Apache Spark作为一种强大的大数据处理工具,可以在集群中高效运行,处理数十TB甚至PB级别的数据。本文将介绍如何构建和管理Spark集群,以满足大规模数据处理的需求。 Spark集群架构…...

DshanMCU-R128s2 SDK 架构与目录结构
R128 S2 是全志提供的一款 M33(ARM)C906(RISCV-64)HIFI5(Xtensa) 三核异构 SoC,同时芯片内部 SIP 有 1M SRAM、8M LSPSRAM、8M HSPSRAM 以及 16M NORFLASH。 本文档作为 R128 FreeRTOS SDK 开发指南,旨在帮助软件开发工程师、技术支持工程师快速上手&am…...

【5G PHY】NR参考信号功率和小区总传输功率的计算
博主未授权任何人或组织机构转载博主任何原创文章,感谢各位对原创的支持! 博主链接 本人就职于国际知名终端厂商,负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作,目前牵头6G算力网络技术标准研究。 博客…...
k8s学习 — 各知识点快捷入口
k8s学习 — 各知识点快捷入口 k8s学习 — 第一章 核心概念 k8s学习 — 第一章 核心概念 命名空间 实践: k8s学习 — (实践)第二章 搭建k8s集群k8s学习 — (实践)第三章 深入Podk8s学习 — (实践࿰…...
【Python】Python 批量转换PDF到Excel
PDF是面向展示和打印使用的,并未考虑编辑使用,所以缺少了很多编辑属性且非常难修改PDF里面的数据。当您需要分析或修改PDF文档数据时,可以将PDF保存为Excel工作簿,实现轻松编辑数据的需求。PDF转Excel,技术关键就是提取…...

Python并行计算和分布式任务全面指南
更多Python学习内容:ipengtao.com 大家好,我是彭涛,今天为大家分享 Python并行计算和分布式任务全面指南。全文2900字,阅读大约8分钟 并发编程是现代软件开发中不可或缺的一部分,它允许程序同时执行多个任务࿰…...

微信小程序promise封装
一. 在utils文件夹内创建一个request.js 写以下封装的 wx.request() 方法 const baseURL https:// 域名 ; //公用总路径地址 export const request (params) > { //暴露出去一个函数,并且接收一个外部传入的参数let dataObj params.data || {}; //…...

hash长度扩展攻击
作为一个信息安全的人,打各个学校的CTF比赛是比较重要的! 最近一个朋友发了道题目过来,发现有道题目比较有意思,这里跟大家分享下 这串代码的大致意思是: 这段代码首先引入了一个名为"flag.php"的文件&am…...

设计模式--命令模式
实验16:命令模式 本次实验属于模仿型实验,通过本次实验学生将掌握以下内容: 1、理解命令模式的动机,掌握该模式的结构; 2、能够利用命令模式解决实际问题。 [实验任务]:多次撤销和重复的命令模式 某系…...
单例模式的七种写法
为什么使用单例? 避免重复创建对象,节省内存,方便管理;一般我们在工具类中频繁使用单例模式; 1.饿汉式(静态常量)-[可用] /*** 饿汉式(静态常量)*/ public class Singleton1 {private static final Singleton1 INSTANCE new Singleton1();private Singleton1(){}…...

ElasticSearch入门介绍和实战
目录 1.ElasticSearch简介 1.1 ElasticSearch(简称ES) 1.2 ElasticSearch与Lucene的关系 1.3 哪些公司在使用Elasticsearch 1.4 ES vs Solr比较 1.4.1 ES vs Solr 检索速度 2. Lucene全文检索框架 2.1 什么是全文检索 2.2 分词原理之倒排索引…...

【FPGA】分享一些FPGA视频图像处理相关的书籍
在做FPGA工程师的这些年,买过好多书,也看过好多书,分享一下。 后续会慢慢的补充书评。 【FPGA】分享一些FPGA入门学习的书籍【FPGA】分享一些FPGA协同MATLAB开发的书籍 【FPGA】分享一些FPGA视频图像处理相关的书籍 【FPGA】分享一些FPGA高速…...
AUTOSAR从入门到精通-车载以太网(四)
目录 前言 原理 车载以太网发展历史 为何选择车载以太网...

MySQL报错:1054 - Unknown column ‘xx‘ in ‘field list的解决方法
我在操作MySQL遇到1054报错,报错内容:1054 - Unknown column Cindy in field list,下面演示解决方法,非常简单。 根据箭头指示,Cindy对应的应该是VARCHAR文本数字类型,字符串要用引号,所以解决方…...
【Android 13】使用Android Studio调试系统应用之Settings移植(四):40+个依赖子模块之ActionBarShadow
文章目录 一、篇头二、系列文章2.1 Android 13 系列文章2.2 Android 9 系列文章2.3 Android 11 系列文章三、子模块AS移植3.1 AS创建目标3.2 创建ActionBarShadow(1)使用VS Code打开org_settings/SettingsLib目录(2)ActionBarShadow的Manifest.xml(3)ActionBarShadow的An…...

nosql-redis整合测试
nosql-redis整合测试 1、创建项目并导入redis2、配置redis3、写测试类4、在redis中创建key5、访问80826、在集成测试中测试方法 1、创建项目并导入redis 2、配置redis 3、写测试类 4、在redis中创建key 5、访问8082 6、在集成测试中测试方法 package com.example.boot3.redis;…...

智能化中的控制与自动化中的控制不同
智能化中的控制相对于自动化中的控制更加灵活、智能、综合和学习能力强。智能化控制系统能够根据实际情况进行自主决策和优化,适用范围更广,效果更好。 首先,智能化控制系统能够根据外部环境的变化和实时数据的反馈来自主调整和优化控制策略&…...

java练习题之多态练习
1:关于多态描述错误的是(D) A. 父类型的引用指向不同的子类对象 B. 用引用调用方法,只能调用引用中声明的方法 C. 如果子类覆盖了父类中方法,则调用子类覆盖后的方法 D. 子类对象类型会随着引用类型的改变而改变 2:class Supe…...

[原创][R语言]股票分析实战[4]:周级别涨幅趋势的相关性
[简介] 常用网名: 猪头三 出生日期: 1981.XX.XX QQ联系: 643439947 个人网站: 80x86汇编小站 https://www.x86asm.org 编程生涯: 2001年~至今[共22年] 职业生涯: 20年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、D…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...

CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...

初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...

Razor编程中@Html的方法使用大全
文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...

计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...

从物理机到云原生:全面解析计算虚拟化技术的演进与应用
前言:我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM(Java Virtual Machine)让"一次编写,到处运行"成为可能。这个软件层面的虚拟化让我着迷,但直到后来接触VMware和Doc…...