当前位置: 首页 > news >正文

FastAPI WebSocket 聊天应用详细教程

在这里插入图片描述
在这里插入图片描述

项目简介

这是一个基于 FastAPI 和 WebSocket 实现的实时聊天应用,支持一对一聊天、离线消息存储等功能。

技术栈

  • 后端:FastAPI (Python)
  • 前端:HTML、JavaScript、CSS
  • 通信:WebSocket
  • 认证:简单的 token 认证

项目结构

├── main.py              # 后端主程序
└── templates/           # 前端模板目录└── chat.html       # 聊天页面

详细代码实现

1. 后端实现 (main.py)

from fastapi import FastAPI, WebSocket, Depends, WebSocketDisconnect
from typing import Dict
import json
from fastapi.responses import HTMLResponse, FileResponse
from fastapi.staticfiles import StaticFilesapp = FastAPI()
app.mount("/templates", StaticFiles(directory="templates"), name="templates")class ConnectionManager:def __init__(self):self.active_connections: Dict[str, WebSocket] = {}self.offline_messages: Dict[str, list] = {}  # 离线消息存储async def connect(self, user: str, websocket: WebSocket):await websocket.accept()self.active_connections[user] = websocketasync def disconnect(self, user: str, websocket: WebSocket):if user in self.active_connections:del self.active_connections[user]async def send_personal_message(self, message: str, to_user: str):if to_user in self.active_connections:await self.active_connections[to_user].send_text(message)return {"success": True}else:# 存储离线消息if to_user not in self.offline_messages:self.offline_messages[to_user] = []self.offline_messages[to_user].append(message)return {"success": False, "reason": "offline", "stored": True}async def get_offline_messages(self, user: str):if user in self.offline_messages:messages = self.offline_messages[user]del self.offline_messages[user]  # 取出后删除return messagesreturn []# Token 认证
async def get_cookie_or_token(token: str = None):if not token:from fastapi import HTTPExceptionraise HTTPException(status_code=401, detail="未授权")return token# 初始化连接管理器
ws_manager = ConnectionManager()@app.websocket("/ws/{user}")
async def websocket_one_to_one(websocket: WebSocket,user: str,cookie_or_token: str = Depends(get_cookie_or_token)
):await ws_manager.connect(user, websocket)# 发送离线消息offline_msgs = await ws_manager.get_offline_messages(user)for msg in offline_msgs:await websocket.send_text(msg)try:while True:data = await websocket.receive_text()message_data = json.loads(data)# 防止自己给自己发消息if message_data["to_user"] == user:error_msg = {"type": "error","content": "不能发送消息给自己"}await websocket.send_text(json.dumps(error_msg))continueresponse_message = {"from": user,"content": message_data["content"],"timestamp": message_data.get("timestamp"),"type": "message"}# 发送消息result = await ws_manager.send_personal_message(message=json.dumps(response_message),to_user=message_data["to_user"])# 处理离线消息if not result["success"]:if result.get("stored"):success_msg = {"type": "info","content": f"消息已保存,将在用户 {message_data['to_user']} 上线时送达"}await websocket.send_text(json.dumps(success_msg))except WebSocketDisconnect:await ws_manager.disconnect(user, websocket)except Exception as e:print(f"WebSocket 错误: {e}")await ws_manager.disconnect(user, websocket)@app.get("/", response_class=FileResponse)
async def root():return "templates/chat.html"

2. 前端实现 (templates/chat.html)

<!DOCTYPE html>
<html>
<head><title>WebSocket Chat</title><style>body {font-family: Arial, sans-serif;max-width: 800px;margin: 0 auto;padding: 20px;}#loginSection {text-align: center;margin-top: 100px;}#chatSection {display: none;}#messages {list-style-type: none;padding: 0;height: 400px;overflow-y: auto;border: 1px solid #ccc;margin-bottom: 20px;padding: 10px;}.message {margin: 10px 0;padding: 10px;border-radius: 5px;background-color: #f0f0f0;}.input-group {margin-bottom: 10px;}input[type="text"] {padding: 8px;margin-right: 10px;width: 200px;}button {padding: 8px 15px;background-color: #4CAF50;color: white;border: none;border-radius: 4px;cursor: pointer;}button:hover {background-color: #45a049;}#logoutBtn {background-color: #f44336;}#logoutBtn:hover {background-color: #da190b;}.error {color: red;margin: 10px 0;}.info {color: blue;margin: 10px 0;}</style>
</head>
<body><!-- 登录部分 --><div id="loginSection"><h1>WebSocket 聊天</h1><div class="input-group"><input type="text" id="loginUsername" placeholder="输入用户名" autocomplete="off"/><button onclick="login()">登录</button></div><div id="loginError" class="error"></div></div><!-- 聊天部分 --><div id="chatSection"><h1>WebSocket 聊天</h1><div id="currentUser"></div><form action="" onsubmit="sendMessage(event)"><div class="input-group"><input type="text" id="messageText" placeholder="输入消息" autocomplete="off"/><input type="text" id="username" placeholder="接收者用户名" autocomplete="off"/><button type="submit">发送</button></div></form><button id="logoutBtn" onclick="logout()">退出</button><ul id='messages'></ul></div><script>let ws = null;function checkLogin() {const token = localStorage.getItem('token');if (token) {document.getElementById('loginSection').style.display = 'none';document.getElementById('chatSection').style.display = 'block';document.getElementById('currentUser').textContent = `当前用户: ${token}`;connectWebSocket();} else {document.getElementById('loginSection').style.display = 'block';document.getElementById('chatSection').style.display = 'none';}}function login() {const username = document.getElementById('loginUsername').value.trim();if (!username) {document.getElementById('loginError').textContent = '请输入用户名';return;}localStorage.setItem('token', username);checkLogin();}function logout() {if (ws && ws.readyState === WebSocket.OPEN) {ws.close();}localStorage.removeItem('token');document.getElementById('messages').innerHTML = '';document.getElementById('messageText').value = '';document.getElementById('username').value = '';document.getElementById('loginSection').style.display = 'block';document.getElementById('chatSection').style.display = 'none';document.getElementById('loginUsername').value = '';document.getElementById('currentUser').textContent = '';}function connectWebSocket() {const token = localStorage.getItem('token');ws = new WebSocket(`ws://localhost:8000/ws/${token}?token=${token}`);ws.onmessage = function(event) {const messages = document.getElementById('messages');const message = document.createElement('li');message.className = 'message';const data = JSON.parse(event.data);if (data.type === 'error') {message.style.color = 'red';message.textContent = data.content;} else if (data.type === 'info') {message.style.color = 'blue';message.textContent = data.content;} else {message.textContent = `${data.from}: ${data.content}`;}messages.appendChild(message);messages.scrollTop = messages.scrollHeight;};ws.onerror = function(error) {console.error('WebSocket 错误:', error);};ws.onclose = function() {console.log('WebSocket 连接已关闭');};}function sendMessage(event) {event.preventDefault();const messageInput = document.getElementById("messageText");const usernameInput = document.getElementById("username");if (!messageInput.value.trim() || !usernameInput.value.trim()) {return;}const messageData = {content: messageInput.value,to_user: usernameInput.value,timestamp: new Date().toISOString()};ws.send(JSON.stringify(messageData));const messages = document.getElementById('messages');const message = document.createElement('li');message.className = 'message';message.style.backgroundColor = '#e3f2fd';message.textContent = `我: ${messageInput.value}`;messages.appendChild(message);messages.scrollTop = messages.scrollHeight;messageInput.value = '';}checkLogin();</script>
</body>
</html>

功能特点

  1. 用户管理

    • 简单的用户名登录系统
    • 用户在线状态管理
    • 用户会话保持
  2. 消息功能

    • 实时一对一聊天
    • 离线消息存储
    • 上线自动接收离线消息
    • 防止自己给自己发消息
  3. 界面特性

    • 响应式设计
    • 消息实时显示
    • 错误信息提示
    • 消息状态反馈
  4. 技术特性

    • WebSocket 实时通信
    • 状态管理
    • 错误处理
    • 会话管理

如何运行

  1. 安装依赖
pip install fastapi uvicorn
  1. 启动服务器
uvicorn main:app --reload
  1. 访问应用
  • 打开浏览器访问 http://localhost:8000
  • 输入用户名登录
  • 开始聊天

使用流程

  1. 登录

    • 输入用户名
    • 点击登录按钮
  2. 发送消息

    • 输入接收者用户名
    • 输入消息内容
    • 点击发送
  3. 接收消息

    • 实时接收其他用户发送的消息
    • 上线时接收离线消息
  4. 退出

    • 点击退出按钮
    • 清除登录状态

相关文章:

FastAPI WebSocket 聊天应用详细教程

项目简介 这是一个基于 FastAPI 和 WebSocket 实现的实时聊天应用&#xff0c;支持一对一聊天、离线消息存储等功能。 技术栈 后端&#xff1a;FastAPI (Python)前端&#xff1a;HTML、JavaScript、CSS通信&#xff1a;WebSocket认证&#xff1a;简单的 token 认证 项目结构…...

【C语言】动态内存的常见错误

前言&#xff1a; 在上章节中讲解了动态内存的概念和管理的核心函数。 在本章节继续为大家介绍动态内存的常见错误&#xff0c;让大家更好的理解运用。 补充&#xff1a;使用内存函数需要头文件<stdlib.h> 对NULL指针的解引用操作 当使用malloc、calloc或realloc等函…...

Missashe考研日记-day24

Missashe考研日记-day24 1 专业课408 学习时间&#xff1a;2h30min学习内容&#xff1a; 今天把剩下的两个经典同步问题和管程部分的课看了&#xff0c;然后做课后习题。这部分的重点在PV大题&#xff0c;很多很经典&#xff0c;不过第一轮不打算做大题&#xff0c;把选择题做…...

精益数据分析(13/126):洞察数据关系,灵活调整创业方向

精益数据分析&#xff08;13/126&#xff09;&#xff1a;洞察数据关系&#xff0c;灵活调整创业方向 大家好&#xff01;在创业和数据分析的探索之路上&#xff0c;每一次的学习都是成长的宝贵机会。今天&#xff0c;咱们接着深入学习《精益数据分析》&#xff0c;一起探索相…...

常用python爬虫框架介绍

文章目录 前言1. Scrapy2. BeautifulSoup 与 Requests 组合3. Selenium4. PySpider 前言 Python 有许多优秀的爬虫框架&#xff0c;每个框架都有其独特的特点和适用场景。以下为你详细介绍几个常用的 Python 爬虫框架&#xff1a; Python 3.13.2 安装教程&#xff08;附安装包…...

HarmonyOS:网络HTTP数据请求

导读 场景介绍接口说明request接口开发步骤requestInStream接口开发步骤证书锁定预置应用级证书预置证书公钥哈希值JSON配置文件示例 场景介绍 通过HTTP发起一个数据请求&#xff0c;支持常见的GET、POST、OPTIONS、HEAD、PUT、DELETE、TRACE、CONNECT方法 接口说明 HTTP数据…...

CoinNexus Chain 推出泰利风暴,开启 Web3.0 智能金融元宇宙科技新时代

4月25日&#xff0c;CoinNexusChain 区块链正式推出开创性的“泰利风暴”&#xff08;Terry Storm&#xff09;&#xff0c;再次展现了其前瞻性的视野和非凡的潜力。这标志着 CoinNexusChain 在 Web3.0 创新浪潮中迈出了重要一步。    Terry是一种创新的 RWA 金融激励机制&…...

编译opencv源码使得opencv-python获得gstreamer支持

我个人习惯在miniconda中使用python版本的opencv&#xff0c;使用pip进行安装时&#xff0c;默认的包并不会有gstreamer支持&#xff0c;我尝试过自己编译opencv-python&#xff0c;编出的包有各种各样的问题。最终还是决定自己从opencv仓库源码自行编译。 安装gstreamer apt…...

眼镜眨巴眨巴-一步几个脚印从头设计数字生命2——仙盟创梦IDE

import cv2 import mediapipe as mp import numpy as np import timemp_drawing mp.solutions.drawing_utils mp_face_mesh mp.solutions.face_mesh# 加载图片 image cv2.imread(wlzc.jpg) # image_height, image_width, _ image.shape# 初始化面部网格模型 with mp_face_…...

django之数据的翻页和搜索功能

数据的翻页和搜素功能 目录 1.实现搜素功能 2.实现翻页功能 一、实现搜素功能 我们到bootstrap官网, 点击组件, 然后找到输入框组, 并点击作为额外元素的按钮。 我们需要使用上面红色框里面的组件, 就是搜素组件, 代码部分就是下面红色框框出来的部分。 把这里的代码复制…...

linux复习

1.关于进程 1.1 概念 用户角度&#xff1a;进程是程序的一次执行实例&#xff0c;也就是正在运行的程序 内核角度&#xff1a;操作系统分配内存和cpu资源的实体 操作系统使用内核数据结构 程序的代码及数据 描述进程&#xff0c;Linux中对应的内核数据结构就是task_struct…...

Post-Processing PropertySource instance详解 和 BeanFactoryPostProcessor详解

PropertySourcesBeanFactoryPostProcessor详解 1. 核心概念 BeanFactoryPostProcessor 是 Spring 框架中用于在 BeanFactory 初始化阶段 对 Environment 中的 PropertySource 进行后处理的接口。它允许开发者在 Bean 创建之前 对属性源进行动态修改&#xff0c;例如添加、删除…...

go 编译的 windows 进程(exe)以管理员权限启动(UAC)

引言 windows 系统&#xff0c;在打开某些 exe 的时候&#xff0c;会弹出“用户账户控制(UAC)”的弹窗 “你要允许来自xx发布者的此应用对你的设备进行更改吗&#xff1f;” UAC&#xff08;User Account Control&#xff0c;用户账户控制&#xff09;是 Windows 操作系统中的…...

Elasticsearch性能优化实践

一、背景与挑战 基金研报搜索场景中&#xff0c;我们面临以下核心挑战&#xff1a; ​数据规模庞大&#xff1a;单索引超500GB原始数据&#xff0c;包含300万份PDF/Word研报文档​查询性能瓶颈&#xff1a;复杂查询平均响应时间超过10秒&#xff0c;高峰期CPU负载达95%​存储…...

【Web API系列】Web Shared Storage API 深度解析:WindowSharedStorage 接口实战指南

前言 在当今 Web 应用日益复杂的背景下&#xff0c;跨页面数据共享与隐私保护已成为现代浏览器技术演进的重要命题。传统 Web 存储方案&#xff08;如 Cookies、LocalStorage&#xff09;在应对多维度用户特征存储、跨上下文数据共享等场景时&#xff0c;逐渐暴露出技术瓶颈与…...

Eureka、LoadBalance和Nacos

Eureka、LoadBalance和Nacos 一.Eureka引入1.注册中心2.CAP理论3.常见的注册中心 二.Eureka介绍1.搭建Eureka Server 注册中心2.搭建服务注册3.服务发现 三.负载均衡LoadBalance1.问题引入2.服务端负载均衡3.客户端负载均衡4.Spring Cloud LoadBalancer1).快速上手2)负载均衡策…...

智能体MCP 实现数据可视化分析

参考: 在线体验 https://www.doubao.com/chat/ 下载安装离线体验 WPS软件上的表格分析 云上创建 阿里mcp:https://developer.aliyun.com/article/1661198 (搜索加可视化) 案例 用cline 或者cherry studio实现 mcp server:excel-mcp-server、quickchart-mcp-server...

3小时速通Python-Python学习总部署、总预览(一)

目录 Python的关键字有哪些&#xff1a; ​编辑 代码&#xff1a;1-5&#xff1a; 代码&#xff1a;6-10&#xff1a; 代码&#xff1a;11-15&#xff1a; 代码&#xff1a;16-20&#xff1a; 代码&#xff1a;21-25&#xff1a; 代码&#xff1a;26-27&#xff1a; Pyt…...

机器学习基础 - 分类模型之决策树

决策树 文章目录 决策树简介决策树三要素1. 特征的选择1. ID32. C4.53. CART2. 剪枝处理0. 剪枝的作用1. 预剪枝2. 后剪枝QA1. ID3, C4.5, CART 这三种决策树的区别2. 树形结构为何不需要归一化?3. 分类决策树与回归决策树的区别4. 为何信息增益会偏向多取值特征?4. 为何信息…...

Java面向对象的三大特性

## 1. 封装&#xff08;Encapsulation&#xff09; 封装是将数据和操作数据的方法绑定在一起&#xff0c;对外部隐藏对象的具体实现细节。通过访问修饰符来实现封装。 示例代码&#xff1a; java public class Student { // 私有属性 private String name; private int age; …...

【Pandas】pandas DataFrame truediv

Pandas2.2 DataFrame Binary operator functions 方法描述DataFrame.add(other)用于执行 DataFrame 与另一个对象&#xff08;如 DataFrame、Series 或标量&#xff09;的逐元素加法操作DataFrame.add(other[, axis, level, fill_value])用于执行 DataFrame 与另一个对象&…...

GTS-400 系列运动控制器板(六)----修改编码器计数方向

运动控制器函数库的使用 运动控制器驱动程序、 dll 文件、例程、 Demo 等相关文件请通过固高科技官网下载,网 址为: www.googoltech.com.cn/pro_view-3.html 1 Windows 系统下动态链接库的使用 在 Windows 系统下使用运动控制器,首先要安装驱动程序。在安装前需要提…...

卷积神经网络迁移学习:原理与实践指南

引言 在深度学习领域&#xff0c;卷积神经网络(CNN)已经在计算机视觉任务中取得了巨大成功。然而&#xff0c;从头开始训练一个高性能的CNN模型需要大量标注数据和计算资源。迁移学习(Transfer Learning)技术为我们提供了一种高效解决方案&#xff0c;它能够将预训练模型的知识…...

Django 入门实战:从环境搭建到构建你的第一个 Web 应用

Django 入门实战&#xff1a;从环境搭建到构建你的第一个 Web 应用 恭喜你选择 Django 作为你学习 Python Web 开发的起点&#xff01;Django 是一个强大、成熟且功能齐全的框架&#xff0c;非常适合构建中大型的 Web 应用程序。本篇将通过一个简单的例子&#xff0c;带你走完…...

【后端】构建简洁的音频转写系统:基于火山引擎ASR实现

在当今数字化时代&#xff0c;语音识别技术已经成为许多应用不可或缺的一部分。无论是会议记录、语音助手还是内容字幕&#xff0c;将语音转化为文本的能力对提升用户体验和工作效率至关重要。本文将介绍如何构建一个简洁的音频转写系统&#xff0c;专注于文件上传、云存储以及…...

http通信之axios vs fecth该如何选择?

在HTTP通信中&#xff0c;axios和fetch都是常用的库或原生API用于发起网络请求。两者各有特点&#xff0c;适用于不同的场景。下面详细介绍它们的差异和各自的优势&#xff1a; fetch 特点&#xff1a; 原生支持&#xff1a;fetch是现代浏览器内置的API&#xff0c;不需要额外…...

iostat指令介绍

文章目录 1. 功能介绍2. 语法介绍3. 应用场景4. 示例分析 1. 功能介绍 iostat (input/output statistics)&#xff0c;是 Linux/Unix 系统中用于监控 CPU 使用率和 磁盘 I/O 性能的核心工具&#xff0c;可实时展示设备负载、吞吐量、队列状态等关键指标。 可以使用 man iostat查…...

NLP高频面试题(五十)——大模型(LLMs)分词(Tokenizer)详解

在自然语言处理(NLP)任务中,将文本转换为模型可处理的数字序列是必不可少的一步。这一步通常称为分词(tokenization),即把原始文本拆分成一个个词元(token)。对于**大型语言模型(LLM,Large Language Model,大型语言模型)**而言,选择合适的分词方案至关重要:分词的…...

桌面我的电脑图标不见了怎么恢复 恢复方法指南

在Windows操作系统中&#xff0c;“我的电脑”或在较新版本中称为“此电脑”的图标&#xff0c;是访问硬盘驱动器、外部存储设备和系统文件的重要入口。然而&#xff0c;有些用户可能会发现桌面上缺少了这个图标&#xff0c;这可能是由于误操作、系统设置更改或是不小心删除造成…...

【Qt】控件的理解 和 基础控件 QWidget 属性详解(通俗易懂+附源码+思维导图框架)

每日激励&#xff1a;“不设限和自我肯定的心态&#xff1a;I can do all things。 — Stephen Curry” 绪论​&#xff1a; 通过上一章对信号槽的理解相信你对Qt的认识肯定有了很大的进步&#xff0c;下面将通过本篇文章带你深入的认识Widget控件&#xff08;主窗口&#xff0…...

oracle将表字段逗号分隔的值进行拆分,并替换值

需求背景&#xff1a;需要源数据变动&#xff0c;需要对历史表已存的字段值根据源数据进行更新。如果是单字段存值&#xff0c;直接根据映射表关联修改即可。但字段里面若存的值是以逗号分割&#xff0c;比如旧值&#xff1a;‘old1,old2,old3’&#xff0c;要根据映射关系调整…...

用c语言实现——一个带头节点的链队列,支持用户输入交互界面、初始化、入队、出队、查找、判空判满、显示队列、遍历计算长度等功能

一、知识介绍 带头节点的链队列是一种基于链表实现的队列结构&#xff0c;它在链表的头部添加了一个特殊的节点&#xff0c;称为头节点。头节点不存储实际的数据元素&#xff0c;主要作用是作为链表的起点&#xff0c;简化队列的操作和边界条件处理。 1.节点结构 链队列的每…...

webpack基础使用了解(入口、出口、插件、加载器、优化、别名、打包模式、环境变量、代码分割等)

目录 1、webpack简介2、简单示例3、入口(entry)和输出(output)4、自动生成html文件5、打包css代码6、优化&#xff08;单独提取css代码&#xff09;7、优化&#xff08;压缩过程&#xff09;8、打包less代码9、打包图片10、搭建开发环境&#xff08;webpack-dev-server&#xf…...

【项目】基于MCP+Tabelstore架构实现知识库答疑系统

基于MCPTabelstore架构实现知识库答疑系统 整体流程设计&#xff08;一&#xff09;Agent 架构&#xff08;二&#xff09;知识库存储&#xff08;1&#xff09;向量数据库Tablestore&#xff08;2&#xff09;MCP Server &#xff08;三&#xff09;知识库构建&#xff08;1&a…...

C语言高频面试题——malloc 和 calloc区别

在 C 语言中&#xff0c;malloc 和 calloc 都是用于动态内存分配的函数&#xff0c;但它们在 内存初始化、参数形式 和 使用场景 上有显著区别。以下是详细的对比分析&#xff1a; 1. 函数原型 malloc void* malloc(size_t size);功能&#xff1a;分配 未初始化 的连续内存块…...

深入探讨JavaScript性能瓶颈与优化实战指南

JavaScript作为现代Web开发的核心语言,其性能直接影响用户体验与业务指标。随着2025年前端应用的复杂性持续增加,性能优化已成为开发者必须掌握的核心技能。本文将从性能瓶颈分析、优化策略、工具使用三个维度,结合实战案例,系统梳理JavaScript性能优化的关键路径。 一、Ja…...

[创业之路-376]:企业法务 - 创业,不同的企业形态,个人承担的风险、收益、税费、成本不同

在企业法务领域&#xff0c;创业时选择不同的企业形态&#xff0c;个人在风险承担、收益分配、税费负担及运营成本方面存在显著差异。以下从个人独资企业、合伙企业、有限责任公司、股份有限公司四种常见形态展开分析&#xff1a; 一、个人承担的风险 个人独资企业 风险类型&…...

【Lua】Lua 入门知识点总结

Lua 入门学习笔记 本教程旨在帮助有编程基础的学习者快速入门Lua编程语言。包括Lua中变量的声明与使用&#xff0c;包括全局变量和局部变量的区别&#xff0c;以及nil类型的概念、数值型、字符串和函数的基本操作&#xff0c;包括16进制表示、科学计数法、字符串连接、函数声明…...

低空经济 WebGIS 无人机配送 | 图扑数字孪生

2024 年&#xff0c;”低空经济” 首次写入政府工作报告&#xff0c;在政策驱动下各地纷纷把握政策机遇&#xff0c;从基建网络、场景创新、产业生态、政策激励等方面&#xff0c;构建 “规划-建设-应用-赋能” 的系统性布局&#xff0c;作为新质生产力的重要体现&#xff0c;推…...

【程序员 NLP 入门】词嵌入 - 如何基于计数的方法表示文本? (★小白必会版★)

&#x1f31f; 嗨&#xff0c;你好&#xff0c;我是 青松 &#xff01; &#x1f308; 希望用我的经验&#xff0c;让“程序猿”的AI学习之路走的更容易些&#xff0c;若我的经验能为你前行的道路增添一丝轻松&#xff0c;我将倍感荣幸&#xff01;共勉~ 【程序员 NLP 入门】词…...

基于机器学习的多光谱遥感图像分类方法研究与定量评估

多光谱遥感技术通过获取可见光至红外波段的光谱信息&#xff0c;为地质勘探、农业监测、环境调查等领域提供了重要支持。与普通数码相机相比&#xff0c;多光谱成像能记录更丰富的波段数据&#xff08;如近红外、短波红外等&#xff09;&#xff0c;从而更精准地识别地物特征。…...

BEVDepth: Acquisition of Reliable Depth for Multi-View 3D Object Detection

背景 基于多视角图片的3D感知被LSS证明是可行的,它使用估计的深度将图像特征转化为3D视椎,再将其压缩到BEV平面上。对于这个得到的BEV特征图,它支持端到端训练以及各种下游任务。但是对于深度估计这一块学习的深度质量如何,到目前为止没有相关工作研究。 贡献 本文的贡献…...

【Linux】静态库 动态库

&#x1f33b;个人主页&#xff1a;路飞雪吖~ &#x1f320;专栏&#xff1a;Linux 目录 一、&#x1f451;静态库和动态库 静态库&#xff1a; 动态库&#xff1a; &#x1f320;手动制作静态库 && 手动调用一下我们自己写的静态库 1> 安装到系统里面 ✨生成静…...

Java转Go日记(六):TCP黏包

服务端代码如下&#xff1a; // socket_stick/server/main.gofunc process(conn net.Conn) {defer conn.Close()reader : bufio.NewReader(conn)var buf [1024]bytefor {n, err : reader.Read(buf[:])if err io.EOF {break}if err ! nil {fmt.Println("read from client…...

(51单片机)LCD显示温度(DS18B20教程)(LCD1602教程)(延时函数教程)(单总线教程)

演示视频&#xff1a; LCD显示温度 源代码 如上图将9个文放在Keli5 中即可&#xff0c;然后烧录在单片机中就行了 烧录软件用的是STC-ISP&#xff0c;不知道怎么安装的可以去看江科大的视频&#xff1a; 【51单片机入门教程-2020版 程序全程纯手打 从零开始入门】https://www.…...

【通过Docker快速部署Tomcat9.0】

文章目录 前言一、部署docker二、部署Tomcat2.1 创建存储卷2.2 运行tomcat容器2.3 查看tomcat容器2.4 查看端口是否监听2.5 防火墙开放端口 三、访问Tomcat 前言 Tomcat介绍 Tomcat 是由 Apache 软件基金会&#xff08;Apache Software Foundation&#xff09;开发的一个开源 …...

云原生--基础篇-3--云原生概述(云、原生、云计算、核心组成、核心特点)

1、什么是云和原生 &#xff08;1&#xff09;、什么是云&#xff1f; “云”指的是云计算环境&#xff0c;代表应用运行的基础设施和资源。依赖并充分利用云计算的弹性、分布式和资源池化能力。 核心含义&#xff1a; 1、云计算基础设施 云原生应用的设计和运行完全基于云…...

Spark-Streaming

Spark-Streaming概述 DStream实操 案例一&#xff1a;WordCount案例 需求&#xff1a;使用 netcat 工具向 9999 端口不断的发送数据&#xff0c;通过 SparkStreaming 读取端口数据并统计不同单词出现的次数 实验步骤&#xff1a; 添加依赖 <dependency> <gro…...

乐视系列玩机------乐视2 x620红灯 黑砖刷写教程以及新版刷写工具的详细释义

乐视x620在上期解析了普通黑砖情况下的救砖刷机过程。但在一些例外的情况下。使用上面的步骤会一直刷写报错 。此种情况就需要另外一种强制刷写方法来救砖 通过博文了解💝💝💝 1💝💝💝-----详细解析乐视2 x620系列 红灯 黑砖线刷救砖的步骤 2💝💝💝----图…...

若依SpringCloud项目-定制微服务模块

若依SpringCloud项目-定制微服务模块 关于微服务先不过多介绍&#xff0c;刚开始熟悉并不能讲的很彻底&#xff0c;成熟的微服务项目-若依SpringCloud就是一个典型的微服务架构工程&#xff08;网上有很多教程了&#xff0c;不明白的可以学习一下&#xff09;。 我正在看的视…...