用TCP实现服务器与客户端的交互
引言:
这篇文章主要是用TCP构造的回显服务器,也就是客户端发什么,就返回什么。用实现这个过程方式来学会TCP套接字的使用。
一、TCP的特点
- TCP是可靠的:这个需要去了解TCP的机制,这是一个大工程,博主后面写好了把连接附上
- TCP是面向字节流的
- TCP是全双工的
- TCP是有连接的
除了可靠性,在编程中无法体会到,其他特性我都会一 一讲解。
二、API介绍
1.ServerSocket
ServerSocket 是创建TCP服务端Socket的API
ServerSocket 构造⽅法:
方法签名 | 方法说明 |
---|---|
ServerSocket(int port) | 创建一个服务端流套接字Socket,并绑定到指定端口 |
⽅法签名 | ⽅法说明 |
---|---|
Socket accpet() | 开始监听指定端口(创建时绑定端口),有客户端连接后,返回一个服务端Socket对象,并基于Socket建立与客户端的连接,否则阻塞等待 |
void close() | 关闭此套接字 |
2.Socket
Socket 是客⼾端Socket,或服务端中接收到客⼾端建⽴连接(accept⽅法)的请求后,返回的服务端Socket。不管是客⼾端还是服务端Socket,都是双⽅建⽴连接以后,保存的对方信息,及⽤来与对⽅收发数据的。
Socket构造方法:
方法签名 | 方法说明 |
---|---|
Socket(String host, int port) | 创建一个客户端流套接字Socket,并与对应IP的主机上,对应端口的进程建立连接。 host:IP地址 prot:端口号 |
这里new出来就是和对方建立完成了。如果建立失败,就会在构造对象的时候抛出异常。
Socket方法:
方法签名 | 方法说明 |
---|---|
InetAddress getInetAddress() | 返回套接字所连接的地址 |
InputStream getInputStream() | 返回此套接字的输⼊流 |
OutputStream getOutputStream() | 返回此套接字的输出流 |
三、实现服务器
服务器需要指定端口号:
public class TcpEchoServer {private ServerSocket serverSocket = null;// 需要指定服务器的端口 处理ServerSocket抛出的异常public TcpEchoServer(int port) throws IOException {// 指定服务器的端口serverSocket = new ServerSocket(port);} }
注意处理抛出的异常
和客户端建立连接:
public class TcpEchoServer {private ServerSocket serverSocket = null;// 需要指定服务器的端口 处理ServerSocket抛出的异常public TcpEchoServer(int port) throws IOException {// 指定服务器的端口serverSocket = new ServerSocket(port);}public void start() throws IOException {//服务器需要不停的执行while (true) {//开始监听指定端口,当有客户端连接后,返回一个保存对方信息的SocketSocket clientSocket = serverSocket.accept();//处理逻辑processConnection(clientSocket);}}//针对一个连接,提供处理逻辑private void processConnection(Socket clientSocket) {} }
这里的accept()就体现了TCP的有连接
当连接成功后,需要处理的逻辑:
//针对一个连接,提供处理逻辑private void processConnection(Socket clientSocket) {//打印客户端的信息 返回IP地址 返回端口号System.out.printf("[%s : %d]客户端上线\n",clientSocket.getInetAddress(), clientSocket.getPort());//获取到socket中持有的流对象try(InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()) {while (true) {//1.获取请求//2.处理请求//3.返回响应//4.打印日志}}catch (IOException e) {}}
全双工的意思:通信的双方(如客户端和服务器)可以在同一时间内同时进行数据的发送和接收,即两个方向的数据流可以同时传输,互不干扰。
这里的getInputStream、getOutputStream就体现了全双工和面向字节流。
不了解这两个接口的可以去看我这篇文章:
JAVA如何操作文件?(超级详细)_java操作文件-CSDN博客
实现处理逻辑:
//针对一个连接,提供处理逻辑private void processConnection(Socket clientSocket) {//打印客户端的信息 返回IP地址 返回端口号System.out.printf("[%s : %d]客户端上线\n",clientSocket.getInetAddress(), clientSocket.getPort());//获取到socket中持有的流对象try(InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()) {//因为我们用字符串来做为数据传输,用Scanner就可以更方便的传输了Scanner scanner = new Scanner(inputStream);//包装输出流,主要是用println()会在数据之后加上\nPrintWriter printWriter = new PrintWriter(outputStream);while (true) {//1.获取请求if (!scanner.hasNext()) {//如果scanner无法读取出数据,说明客户端断开了连接,导致服务器这边读取到”末尾“break;}//2.处理请求//接收客户端的请求//如果遇到 空白字符 就会停止输入String request = scanner.next();//处理请求String response = process(request);//3.返回响应//此处可以按字节数组的形式,但是我们要输入的是字符串,这个就不太方便//outputStream.write(response.getBytes());//此方法在写入之后会自动加上\nprintWriter.println(response);//4.打印日志System.out.printf("[%s : %d] 请求 = %s 响应 = %s \n",clientSocket.getInetAddress(),clientSocket.getPort(),request,response);}}catch (IOException e) {throw new RuntimeException();}}private String process(String request) {//由于我们是回显服务器这里直接返回就可以了return request;}
注意里面使用了两个接口包装了一下输入输出流,最主要的是可以在用\n做为分割。
注意里面的:
发送字符串给客户端,最后会自动加上 \n 做为结尾
println(response);
接收客户端信息,以空白符做为结尾。
空白符:包括不限于 空格、回车、制表符……
scanner.next();
如果是nextLine()就比较严格,必须是\n做为结尾
这里的服务器处理逻辑就写完了,但其实这里还有三个错误,后面再单独讲解:
public class TcpEchoServer {private ServerSocket serverSocket = null;// 需要指定服务器的端口 处理ServerSocket抛出的异常public TcpEchoServer(int port) throws IOException {// 指定服务器的端口serverSocket = new ServerSocket(port);}public void start() throws IOException {//服务器需要不停的执行while (true) {//开始监听指定端口,当有客户端连接后,返回一个保存对方信息的SocketSocket clientSocket = serverSocket.accept();//处理逻辑processConnection(clientSocket);}}//针对一个连接,提供处理逻辑private void processConnection(Socket clientSocket) {//打印客户端的信息 返回IP地址 返回端口号System.out.printf("[%s : %d]客户端上线\n",clientSocket.getInetAddress(), clientSocket.getPort());//获取到socket中持有的流对象try(InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()) {//因为我们用字符串来做为数据传输,用Scanner就可以更方便的传输了Scanner scanner = new Scanner(inputStream);//包装输出流,主要是用println()会在数据之后加上\nPrintWriter printWriter = new PrintWriter(outputStream);while (true) {//1.获取请求if (!scanner.hasNext()) {//如果scanner无法读取出数据,说明客户端断开了连接,导致服务器这边读取到”末尾“break;}//2.处理请求//接收客户端的请求//如果遇到 空白字符 就会停止输入String request = scanner.next();//处理请求String response = process(request);//3.返回响应//此处可以按字节数组的形式,但是我们要输入的是字符串,这个就不太方便//outputStream.write(response.getBytes());//此方法在写入之后会自动加上\nprintWriter.println(response);//4.打印日志System.out.printf("[%s : %d] 请求 = %s 响应 = %s \n",clientSocket.getInetAddress(),clientSocket.getPort(),request,response);}}catch (IOException e) {throw new RuntimeException();}}private String process(String request) {//由于我们是回显服务器这里直接返回就可以了return request;}public static void main(String[] args) throws IOException {TcpEchoServer server = new TcpEchoServer(8080);server.start();} }
四、实现客户端
指定服务器的IP和端口号:
public class TcpEchoClient {private Socket socket = null;public TcpEchoClient(String serverIP, int serverPort) throws IOException {//这里只要建立实例,就是和服务端的accept()建立了连接//socket也就保存了服务器的IP和端口号等//需要传入服务器的 IP地址 和 端口号socket = new Socket(serverIP, serverPort);}public void start() {System.out.println("客户端启动!");}}
整体逻辑:
public class TcpEchoClient {private Socket socket = null;public TcpEchoClient(String serverIP, int serverPort) throws IOException {//需要传入服务器的 IP地址 和 端口号//这里只要建立实例,就是和服务端的accept()建立了连接socket = new Socket(serverIP, serverPort);}public void start() {System.out.println("客户端启动!");try(OutputStream outputStream = socket.getOutputStream();InputStream inputStream = socket.getInputStream()) {while (true) {//1.从控制台获取数据//2.将数据发送给服务器//3.接收服务器响应//4.打印相关结果}}catch (IOException e) {throw new RuntimeException();}} }
整体逻辑实现:
public class TcpEchoClient {private Socket socket = null;public TcpEchoClient(String serverIP, int serverPort) throws IOException {//这里只要建立实例,就是和服务端的accept()建立了连接//socket也就保存了服务器的IP和端口号等//需要传入服务器的 IP地址 和 端口号socket = new Socket(serverIP, serverPort);}public void start() {System.out.println("客户端启动!");try(OutputStream outputStream = socket.getOutputStream();InputStream inputStream = socket.getInputStream()) {//用来接收服务器的信息Scanner scanner = new Scanner(inputStream);//用于接收用户输入Scanner scannerIn = new Scanner(System.in);//用于输出数据给服务器PrintWriter printWriter = new PrintWriter(outputStream);while (true) {//1.从控制台获取数据System.out.print("->");String request = scannerIn.next();//2.将数据发送给服务器printWriter.println(request);//3.接收服务器响应//判断服务端是否还有信息if (!scanner.hasNext()) {break;}//接收服务端信息String response = scanner.next();//4.打印相关结果System.out.println(response);}}catch (IOException e) {throw new RuntimeException();}}public static void main(String[] args) throws IOException { // 127.0.0.1是专门用来访问自己的TcpEchoClient client = new TcpEchoClient("127.0.0.1",8080);client.start();} }
这里仍然纯在一个问题,一会和服务器的问题一起将
五、测试解决bug
最后我会把所有的问题解决了,再把源附上
1. 客户端发送了数据之后,并没有响应
先运行服务器,再运行客户端
可以看到目前还是成功的,那么我们来输入数据。
我们在客户端输入了消息,但是没有任何反应了!
此处的情况是,客户端并没有真正把请求发出去:
PrintWriter这样的类,以及很多IO流中的类,都是 “自带缓冲区” 的。
此方法就带有缓冲区:
printWriter.println(request);
引入缓冲区之后,进行写入数据的操作,并不会马上触发IO,而是先放到内存缓冲区中,等到缓冲区里攒了一波之后,再统一进行发送。
为什么引入缓冲区的机制?
因为IO操作其实是不小的开销,如果数据量较少,那么每一次都进行IO,就有很大一部分开销是IO操作。如果积累到一定数据量再进行IO操作,那么一次IO就传输了这么多数据。
我们可以使用flush方法,主动“刷新缓冲区”:
注意:
服务器 和 客户端 都需要在printWriter.println();后面加上flush()方法。
再来测试:
此时就可以接收到了
2.clientSocket没有执行close()操作
这个问题比较隐蔽,这些ServerSocket 和 Socket 每一次都会在“文件描述符”中创建一个新的表项。
文件描述符:描述了该进程都要操作哪些文件。数组的每个元素就是一个struct file对象,每个结构体就描述了对应的文件信息,数组的小标就称为“文件描述符”。
每次打开一个文件,就想当于在数组上占用了一个位置,而这个数组又是不能扩容的,如果数组满了就会打开文件失败。除非主动调用close才会关闭文件,或者这个进程直接结束了这个数组也被带走了。
那么我们就需要处理一下clientSocket:
3.尝试使用多个客户端同时连接服务器
要对同一代码启动多个进程,需要设置一下步骤:
分别启动客户端1 和 客户端2 ,可以看到服务器上根本没有第二个客户端启动的信息:
原因:
我们可以用多线程去执行专门执行每一个客户端的请求:
public void start() throws IOException {//服务器需要不停的执行while (true) {//开始监听指定端口,当有客户端连接后,返回一个保存对方信息的SocketSocket clientSocket = serverSocket.accept();//让一个线程去对应一个客户端Thread thread = new Thread(() -> {//处理逻辑processConnection(clientSocket);});thread.start();}}
结果:
bug问题解决了,但还有一些场景,可能会把服务器干崩溃
六、优化
1.短时间有大量客户端访问并断开连接
一旦短时间内有大量的客户端,并且每个客户端请求都是很快的连接之后并退出的,这个时候对于服务器来说,就会有比较大的压力。这个时候,就算是进程比线程更加的轻量,但是短时间内有大量的线程创建销毁,就无法忽略它的开销了。
我们可以引入线程池,这样就解决了这个问题:
public void start() throws IOException {//服务器需要不停的执行while (true) {//开始监听指定端口,当有客户端连接后,返回一个保存对方信息的SocketSocket clientSocket = serverSocket.accept();ExecutorService service = Executors.newCachedThreadPool();// //让一个线程去对应一个客户端 // Thread thread = new Thread(() -> { // //处理逻辑 // try { // processConnection(clientSocket); // } catch (IOException e) { // e.printStackTrace(); // } // }); // thread.start();service.submit(() -> {try {processConnection(clientSocket);} catch (IOException e) {e.printStackTrace();}});}}
这个线程可创建的线程数是很大的:
2.有大量的客户端长时间在线访问
例如直播这样的情况,每个客户端分配一个线程,对于一个系统来说,这里搞几百个线程压力就非常大了。所以这里 线程池/线程 都不太适用了。
可以使用 IO多路复用 ,也就是一个线程分配多个客户端进行服务,因为大部分时间线程都是在等待状态,就能够让线程分配多个客户端,这样的机制我们做为java程序员不需要过多了解,这样的机制以及被大佬们,装进各种框架中了。
相关文章:
用TCP实现服务器与客户端的交互
引言: 这篇文章主要是用TCP构造的回显服务器,也就是客户端发什么,就返回什么。用实现这个过程方式来学会TCP套接字的使用。 一、TCP的特点 TCP是可靠的:这个需要去了解TCP的机制,这是一个大工程,博主后面写…...
用于实时辐射场渲染的3D高斯溅射——3D Gaussian Splatting for Real-Time Radiance Field Rendering
用于实时辐射场渲染的3D高斯溅射——3D Gaussian Splatting for Real-Time Radiance Field Rendering 文章目录 用于实时辐射场渲染的3D高斯溅射——3D Gaussian Splatting for Real-Time Radiance Field Rendering摘要Abstract1. 预备知识1.1 三维的几何表示1.2 计算机中的集合…...
Vue3 Echarts 3D立方体柱状图实现教程
文章目录 前言一、实现原理二、series ——type: "pictorialBar" 简介2.1 常用属性 三、代码实战3.1 封装一个echarts通用组件 echarts.vue3.2 实现一个立方体柱状图(1)首先实现一个基础柱状图(2)添加立方体棱线&#x…...
Soildworks怎样在装配体中建立局部剖视图
1思路:建立拉伸切除 2步骤 1-打开点线面显示按钮 2-在装配体中依据某个基准面(例如前视基准面)建立一个待切除的草图 3-点击顶部工具栏的装配体--->装嫩配体特征---->拉伸切除---Ok 3具体图示 1-点击,使其变成灰色 即…...
基于C++的IOT网关和平台5:github项目ctGateway开发指南
初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。 源码指引:github源码指引_初级代码游戏的博客-CSDN博客 …...
虚拟机centos7安装docker
虚拟机CentOS 7上安装 Docker流程 1. 更新系统软件包 需要确保系统软件包是最新的 sudo yum -y update sudo:以超级用户权限执行命令。 yum:CentOS的包管理器工具。 -y:自动确认所有提示,直接执行。 2. 安装 Docker 依赖 在安装 …...
11.Spring Boot 3.1.5 中使用 SpringDoc OpenAPI(替代 Swagger)生成 API 文档
Spring Boot 3.1.5 中使用 SpringDoc OpenAPI(替代 Swagger)生成 API 文档 1. 项目结构 假设项目名为 springboot-openapi-demo,以下是项目的基本结构: springboot-openapi-demo/ ├── src/ │ ├── main/ │ │ ├─…...
pytorch对应gpu版本是否可用判断逻辑
# gpu_is_ok.py import torchdef check_torch_gpu():# 打印PyTorch版本print(f"PyTorch version: {torch.__version__}")# 检查CUDA是否可用cuda_available torch.cuda.is_available()print(f"CUDA available: {cuda_available}")if cuda_available:# 打印…...
Kubernetes 集群概念详解
Kubernetes 集群概念详解 Kubernetes 集群是由多个计算节点组成的容器编排系统,用于自动化部署、扩展和管理容器化应用。以下是 Kubernetes 集群的核心概念和架构解析: 一、集群基础架构 1. 集群组成要素 graph TBMaster[控制平面] --> Node1[工作…...
BT137-ASEMI机器人功率器件专用BT137
编辑:LL BT137-ASEMI机器人功率器件专用BT137 型号:BT137 品牌:ASEMI 封装:TO-220F 批号:最新 引脚数量:3 封装尺寸:如图 特性:双向可控硅 工作结温:-40℃~150℃…...
ArcGIS+GPT:多领域地理分析与决策新方案
技术点目录 AI大模型应用ArcGIS工作流程及功能prompt的使用技巧AI助力工作流程AI助力数据读取AI助力数据编辑与处理AI助力空间分析AI助力遥感分析AI助力二次开发AI助力科研绘图ArcGISAI综合应用了解更多 ——————————————————————————————————…...
鸿蒙文件上传-从前端到后端详解,对比jq请求和鸿蒙arkts请求区别,对比new FormData()和鸿蒙arktsrequest.uploadFile
需要权限:ohos.permission.INTERNET 1.nodejs自定义书写上传后端接口 传输过来的数据放在files?.image下 router.post(/upload,(req, res) > {var form new multiparty.Form();form.uploadDirpublic/images/uploads; //上传图片保存的地址(目录必须存在)fo…...
【DBeaver】如何连接MongoDB
MongoDB驱动 在 DBeaver 社区版是没有的,得自己下载 一、下载mongo-jdbc-standalone.jar 二、在工具栏找到数据库,选择驱动管理器 三、在驱动管理器点击新建 四、选择库,添加mongo-jdbc-standalone.jar;然后点击找到类 五、选择设置&#x…...
Unity 粒子同步,FishNet
Github的工程 同步画面 使用FishNet插件同步,可使用这个选项来克隆第二个项目进行测试...
自然语言处理之命名实体识别:Bi-LSTM-CRF模型的评估与性能分析
命名实体识别(Named Entity Recognition, NER)是自然语言处理(NLP)的核心任务之一,旨在从文本中识别出具有特定意义的实体(如人名、地名、机构名等),并为其分类。随着深度学习的发展,**Bi-LSTM-CRF**(双向长短期记忆网络结合条件随机场)模型因其强大的序列建模能力成…...
【SpringBoot】基于mybatisPlus的博客系统
1.实现用户登录 在之前的项目登录中,我使用的是Session传递用户信息实现校验登录 现在学习了Jwt令牌技术后我尝试用Jwt来完成校验工作 Jwt令牌 令牌一词在网络编程一节我就有所耳闻,现在又拾了起来。 这里讲应用:令牌也就用于身份标识&a…...
[Android]任务列表中有两个相机图标
现象: 修改AndroidManifest.xml <activityandroid:name"com.android.camera.PermissionsActivity"android:label"string/app_name"android:launchMode"singleTop"android:configChanges"orientation|screenSize|keyboardH…...
VINS-FUSION:配置参数说明与配置自己的参数
文章目录 📚简介📍配置文件说明📷相机配置参数🔧设备参数🎯配置自己的参数📷相机参数🔧设备参数📚简介 VINS-Fusion 是一个基于优化的多传感器状态估计器,实现了视觉惯性里程计(VIO)和视觉惯性全球导航卫星系统(VI-GNSS)融合。 📍配置文件说明 VINS-Fus…...
Polars: 新一代高性能数据处理库
<------最重要的是订阅“鲁班模锤”------> 在数据科学和数据分析领域,性能和效率一直是从业者关注的焦点。随着数据量的爆炸式增长,传统的数据处理工具如pandas在处理大规模数据时逐渐显露出其局限性。在这样的背景下,一个名为Polars…...
大屏/门户页面兼容各种分辨率或电脑缩放
需求要求: 需要支持缩放功能(缩放后 页面各元素模块正常展示)、 需要适配各种分辨率(初始加载不应出现横向滚动条) 选择的实现方案 利用 zoom 或者 transform 来缩放兼容页面样式,不动业务模块代码 const isMobile /iPhone|iPad|iPod|Android|Harmony/i.test(navi…...
自定义项目中导入文件import顺序
项目中import 顺序 分类顺序 可以根据模块或文件的功能、类型等进行分类,比如将所有的组件放在一起、工具函数放在一起等。这样的组织方式更有利于对项目结构和代码逻辑的理解,当需要查找某一类功能的代码时,可以快速定位到相应的 import 区…...
Git 本地提交撤销
引言 在 Git 版本控制系统中,偶尔会遇到需要撤销本地提交的情况。本文将详细介绍如何优雅地处理这种情况,帮助您在不慌乱的情况下恢复错误提交。 撤销本地提交的主要方法 当您意外提交了错误文件到 Git 仓库,但尚未推送到远程服务器时&…...
k8s术语之Replication Controller
Replication Controller 在kubernetes中简称RC,它其实是定义了一个期望的场景,即声明某种Pod的副本数量在任意时刻都符合某个预期值,包括一下几个值: 1.Pod期待的副本数(replicas) 2.用于筛选目标Pod的Lable Selector 3.当…...
AI驱动视频批量智能混剪软件生产技术实践
一、引言:短视频工业化生产的技术革新 在电商带货、知识分享等领域,高效产出差异化视频内容成为核心竞争力。本文结合AI技术与工程实践,解析如何通过智能素材处理、参数化合成引擎、多维度质量控制构建全自动视频生产流水线,实现…...
SPL 量化 回测
回测是一种评估交易策略的通用方法。它通过计算策略在历史数据上的表现来评估交易策略的可行性。如果回测结果良好,交易者和分析师可能会有信心在未来继续使用该策略。 1. 回测脚本 首先要编写回测脚本,将回测脚本保存为 backtest.splx。 脚本代码如下…...
2025年“深圳杯”数学建模挑战赛A题-芯片热弹性物理参数估计
芯片热弹性物理参数估计 小驴数模 当今时代,芯片无疑是现代社会发展的 “核心引擎”。它深度嵌入智能手机,实现全球即时通讯;助力汽车智能驾驶,精准导航、自动操控;赋能工业自动化生产线,高效运转。但随着…...
前端笔记-Element-Plus
结束了vue的基础学习,现在进一步学习组件 Element-Plus部分学习目标: Element Plus1、查阅官方文档指南2、学习常用组件的使用方法3、Table、Pagination、Form4、Input、Input Number、Switch、Select、Date Picker、Button5、Message、MessageBox、N…...
vue3封装全局方法
场景:各个模块详情中存在附件列表数据,需要再每个中添加一个预览附件的方法,是后期提出的需求,所以要在每个模块中进行添加,就去将预览方法封装一下。 将公共方法封装在utils下 utils/filePreview.ts import router…...
Django 学习指南:从入门到精通(大体流程)
想要快速掌握 Django 开发技能吗?按照以下学习流程,带你从零基础成长为独立开发 Web 应用的高手。 一、准备工作:打下坚实基础 在开启 Django 之旅前,先确保你已掌握以下 Python 基础知识: 数据类型:熟悉数…...
Java对集合进行操作,赋值新字段
1、方法一:增强for循环 List<Refund> list refundService.selectRefundList(queryParam); for (Refund refund : list) {refund.setPayWay(refund.getPaymentMethod()); // 将支付方式赋值给付款方式 }在 Java 中,当你使用 for 循环遍历 List<…...
【网工第6版】第6章 网络安全③
目录 ■ 虚拟专用网VPN ◆虚拟专用网基础 ◆VPN分类 ▲根据应用场景不同分类 ▲根据VPN技术实现的网络层次分类 ◎ 二层隧道协议:L2TP和PPTP ◎ 网络层隧道协议:IPSec和GRE ※ IPSec IPSec基础 IPSec原理 IPSec两种封装模式 ※ GRE ■ 应用…...
20250430在ubuntu14.04.6系统上查看系统实时网速
rootrootubuntu:~$ sudo apt-get install iftop 【不需要root权限】 rootrootubuntu:~$ sudo apt-get install nload rootrootubuntu:~$ sudo apt-get install vnstat 【失败】 rootrootubuntu:~$ sudo apt-get install speedtest-cli rootrootubuntu:~$ sudo apt-get install …...
远程 Debugger 多用户环境下的用户隔离实践
远程 Debugger 多用户环境下的用户隔离实践 在现代分布式开发和云原生环境下,远程 Debugger 的应用愈发普遍。然而,随着多人协作和多租户场景的出现,**远程 Debugger 的“用户隔离”**变得至关重要。只有实现了良好的用户隔离,才…...
Neo4j多关系或多路径
目录 一、双向关系 1.创建2个节点间的双向关系 2.创建多个路径的节点,双向关系 3.查询带有方向性的关系 4.查询路径上的多个关系 5.查询出a到b的最短距离 6.查询特定长度的路径 二、将之前的关系清空下,如图所示,在操作一次 1.查询出…...
Locate 3D:Meta出品自监督学习3D定位方法
标题: Locate 3D: Real-World Object Localization via Self-Supervised Learning in 3D 摘要: 我们提出了 Locate 3D,这是一种可根据指代表达(如“沙发和灯之间的小咖啡桌”)在三维场景中定位物体的模型。Locate 3…...
Copilot for Excel 一键词云分析与情绪分析
在Excel中使用copilot对数据进行高级分析,我们已经领略过copilot的强悍能力: 零代码、超越DeepSeek:Excel高级数据分析,copilot加持、Python助力 Python in Excel高级分析:一键RFM分析 然而,很多时候我们…...
【Linux 网络】网络工具ifconfig和iproute/iproute2工具详解
【Linux 网络】网络工具ifconfig和iproute/iproute2工具详解 前言1、安装2、常用命令3、命令使用详解 前言 本篇文章主要介绍Linux下网络工具ifconfig/iproute(iproute2)的安装、使用示例和场景。操作系统Ubuntu 18.04。 1、安装 使用apt-get install 命令安装ifconfig和ipr…...
硬盘分区丢失≠末日!3步逻辑恢复法+物理修复全流程图解
引言:硬盘分区丢失——数据安全的“隐形杀手” 在数字化时代,硬盘作为数据存储的核心载体,承载着个人、企业乃至社会的关键信息。然而,硬盘分区丢失这一突发状况,往往让用户措手不及:文件系统突然报错、盘…...
数据接收全流程图(物理网卡 → 应用层)
以下是 DPDK VPP 在 Linux 系统中从网卡收包到应用层的完整数据流程图及分步解析,结合了内核旁路和用户态协议栈的协同工作: 数据接收全流程图(物理网卡 → 应用层) plaintext 复制 下载 ----------------------------------…...
【AI】DeepSeek 流程图 / 时序图制作,Word 排版错乱问题,文字转直观图形
一:动态流程图 / 时序图制作(DeepSeek Draw.IO) 工具准备 DeepSeek(AI 生成代码):官网(免费)Draw.IO(可视化渲染):官网(免费&#…...
C++继承(上)
目录 一、继承的概念及定义 1. 继承的概念 2. 继承的定义 2.1 定义格式 2.2 继承关系和访问限定符 2.3 继承基类成员访问方式的变化 二、基类和派生类对象赋值转换 三、继承中的作用域 四、派生类的默认成员函数 一、继承的概念及定义 1. 继承的概念 继承是面向对象编…...
分布式-redisson
分布式锁redisson 加锁流程缓存相关问题 加锁流程 redisson底层通过lua脚本实现加锁的原子性lock动作包含:加锁、设置超时时间、锁续命未获取到锁的线程通过获取信号量许可等待,所释放后释放信号量通知等待线程 缓存相关问题 缓存失效(击穿…...
Java学习手册:Spring MVC 架构与实现
一、Spring MVC 概述 Spring MVC 是 Spring 框架的一个模块,它提供了一套 Web 应用开发的解决方案,实现了 MVC(Model-View-Controller)设计模式。Spring MVC 提供了清晰的分离逻辑层、视图层和控制器层的结构,便于开发…...
第四部分:实用应用开发
本部分将涵盖以下关键主题: 视频处理基础 视频读取与保存视频帧处理实战:视频中运动目标追踪 条形码与二维码识别 条形码检测原理(概念)QR 码识别实战:制作二维码扫描器 文本识别入门 (OCR) 图像预处理使用 Tesseract…...
目标检测YOLO实战应用案例100讲-基于多级特征融合的小目标深度检测网络
目录 知识储备 基于多级特征融合的小目标深度检测网络实现 一、环境配置 二、核心代码实现 1. 多级特征融合模块(models/fpn.py ) 2. 主干网络(models/backbone.py ) 3. 检测头(models/detector.py ) 三、完整网络架构(models/net.py ) 四、训练代码(train.p…...
单片机-89C51部分:11、IIC 、传感器温湿度
飞书文档https://x509p6c8to.feishu.cn/wiki/Cczpw4oBeiyK71kFhKfcXkQmnad 一、简介 IIC协议,又称I2C协议,是由PHILP公司在80年代开发的两线式串行总线,用于连接微控制器及其外围设备,IIC属于半双工同步通信方式。 C IIC是一种同…...
Java从入门到精通 - Java入门
Java 入门 此笔记参考黑马教程,仅学习使用,如有侵权,联系必删 文章目录 Java 入门01 Java快速入门1. Java 是什么?能干什么?1.1 Java 背景知识1.2 Java 能做什么?1.3 Java 技术体系 2. 如何使用 Java&…...
SLAM中的状态估计理论:从基础到前沿的完整解析
SLAM中的状态估计理论:从基础到前沿的完整解析 一、SLAM状态估计基础与问题建模 1.状态估计问题的数学描述 在SLAM(Simultaneous Localization and Mapping,同时定位与地图构建)中,状态估计问题的核心在…...
Android 自带的分享功能分享到三方应用
1. 分享视频到三方应用 var shareIntent Intent(Intent.ACTION_SEND)shareIntent.setType("video/*")shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(path))startActivity(Intent.createChooser(shareIntent, "")) 2. 分享音频到三方应用 var sha…...
宇树科技开启“人形机器人格斗盛宴”
2025年5月至6月,一场备受瞩目的全球性科技盛事——全球首届“人形机器人格斗大赛”将由杭州宇树科技隆重开启。赛事将带来前所未有的机器人格斗视觉冲击,吸引全球目光聚焦。 为打造顶级参赛队伍,宇树科技的技术精英团队已连续多周开展密集的算…...