You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
12 KiB
12 KiB
后端结构
本文档详细介绍 Rust 后端的代码结构、模块功能和核心实现。
目录结构
src-tauri/src/
├── commands/ # Tauri 命令(前端调用入口)
├── discovery/ # UDP 设备发现
├── websocket/ # WebSocket 聊天
├── http/ # HTTP 文件传输
├── tls/ # TLS 加密
├── database/ # SQLite 数据库
├── models/ # 数据模型
├── utils/ # 工具函数
├── state.rs # 全局状态
├── main.rs # 程序入口
└── lib.rs # 库入口
核心模块详解
1. Commands 模块
Tauri 命令是前端与后端通信的桥梁。
discovery_commands.rs
// 启动设备发现服务
#[tauri::command]
pub async fn start_discovery(app: AppHandle) -> CommandResult<()>;
// 停止设备发现服务
#[tauri::command]
pub async fn stop_discovery() -> CommandResult<()>;
// 获取在线设备列表
#[tauri::command]
pub async fn get_online_devices() -> CommandResult<Vec<DeviceInfo>>;
// 获取本机设备信息
#[tauri::command]
pub fn get_local_device() -> CommandResult<DeviceInfo>;
chat_commands.rs
// 启动 WebSocket 服务
#[tauri::command]
pub async fn start_ws_server(app: AppHandle) -> CommandResult<()>;
// 连接到指定设备
#[tauri::command]
pub async fn connect_to_device(device_id: String) -> CommandResult<()>;
// 发送聊天消息
#[tauri::command]
pub async fn send_chat_message(
device_id: String,
content: String,
message_type: String,
) -> CommandResult<ChatMessage>;
// 获取聊天历史
#[tauri::command]
pub async fn get_chat_history(
device_id: String,
limit: Option<usize>,
offset: Option<usize>,
) -> CommandResult<Vec<ChatMessage>>;
file_commands.rs
// 启动 HTTP 文件服务
#[tauri::command]
pub async fn start_http_server(app: AppHandle) -> CommandResult<()>;
// 选择要发送的文件
#[tauri::command]
pub async fn select_file(app: AppHandle) -> CommandResult<Option<FileMetadata>>;
// 发送文件
#[tauri::command]
pub async fn send_file(
app: AppHandle,
device_id: String,
file_id: String,
file_path: String,
) -> CommandResult<FileTransfer>;
// 取消传输
#[tauri::command]
pub async fn cancel_transfer(file_id: String) -> CommandResult<()>;
// 获取传输历史
#[tauri::command]
pub async fn get_transfer_history(
device_id: String,
limit: Option<usize>,
) -> CommandResult<Vec<FileTransfer>>;
// 打开文件位置
#[tauri::command]
pub async fn open_file_location(path: String) -> CommandResult<()>;
config_commands.rs
// 获取应用配置
#[tauri::command]
pub fn get_app_config() -> CommandResult<AppConfig>;
// 更新设备名称
#[tauri::command]
pub async fn update_device_name(name: String) -> CommandResult<()>;
// 更新下载目录
#[tauri::command]
pub fn update_download_dir(path: String) -> CommandResult<()>;
2. Discovery 模块
UDP 广播设备发现服务。
service.rs
pub struct DiscoveryService {
socket: Arc<UdpSocket>,
local_device: DeviceInfo,
running: Arc<AtomicBool>,
}
impl DiscoveryService {
// 创建服务
pub async fn new(local_device: DeviceInfo, port: u16) -> Result<Self>;
// 启动广播和监听
pub async fn start(&self, app: AppHandle);
// 停止服务
pub fn stop(&self);
// 发送广播
async fn broadcast(&self);
// 处理收到的消息
async fn handle_message(&self, data: &[u8], addr: SocketAddr, app: &AppHandle);
}
manager.rs
pub struct DeviceManager {
devices: DashMap<String, DeviceInfo>,
}
impl DeviceManager {
// 添加/更新设备
pub fn add_or_update(&self, device: DeviceInfo);
// 移除设备
pub fn remove(&self, device_id: &str);
// 获取设备
pub fn get(&self, device_id: &str) -> Option<DeviceInfo>;
// 获取所有设备
pub fn get_all(&self) -> Vec<DeviceInfo>;
// 清理过期设备
pub fn cleanup_stale(&self, max_age: Duration) -> Vec<String>;
}
3. WebSocket 模块
WebSocket 实时聊天服务。
server.rs
pub struct WsServer {
port: u16,
running: Arc<AtomicBool>,
}
impl WsServer {
// 启动服务
pub async fn start(&self, app: AppHandle, connection_manager: ConnectionManager);
// 处理新连接
async fn handle_connection(
stream: TcpStream,
addr: SocketAddr,
app: AppHandle,
connection_manager: ConnectionManager,
);
}
client.rs
pub struct WsClient;
impl WsClient {
// 连接到设备
pub async fn connect(
device: &DeviceInfo,
local_device: &DeviceInfo,
connection_manager: &ConnectionManager,
) -> Result<()>;
// 发送消息
pub async fn send_message(
connection_manager: &ConnectionManager,
device_id: &str,
message: &str,
) -> Result<()>;
}
connection.rs
pub struct ConnectionManager {
// device_id -> write half of WebSocket
connections: DashMap<String, SplitSink<WebSocketStream<TcpStream>, Message>>,
}
impl ConnectionManager {
// 添加连接
pub fn add(&self, device_id: String, sink: SplitSink<...>);
// 移除连接
pub fn remove(&self, device_id: &str);
// 发送消息
pub async fn send(&self, device_id: &str, message: &str) -> Result<()>;
// 检查连接状态
pub fn is_connected(&self, device_id: &str) -> bool;
}
4. HTTP 模块
HTTPS 文件传输服务。
server.rs
pub struct HttpServer {
port: u16,
}
impl HttpServer {
// 启动服务
pub async fn start(&self, app: AppHandle, download_dir: PathBuf) -> Result<()>;
// 创建路由
fn create_router(app: AppHandle, download_dir: PathBuf) -> Router;
}
handlers.rs
// 文件上传处理
pub async fn upload_handler(
State(state): State<AppState>,
mut multipart: Multipart,
) -> impl IntoResponse;
// 文件下载处理
pub async fn download_handler(
Path(file_id): Path<String>,
State(state): State<AppState>,
) -> impl IntoResponse;
client.rs
pub struct HttpClient {
app_handle: Arc<RwLock<Option<AppHandle>>>,
}
impl HttpClient {
// 上传文件(支持取消)
pub async fn upload_file_with_cancel(
&self,
device: &DeviceInfo,
file_path: &PathBuf,
file_id: &str,
from_device: &str,
cancel_token: CancellationToken,
) -> Result<()>;
// 发送进度事件
fn emit_progress(&self, file_id: &str, progress: f64, ...);
}
5. TLS 模块
TLS 证书生成和配置。
certificate.rs
pub struct CertificateManager;
impl CertificateManager {
// 加载或生成证书
pub fn load_or_generate(data_dir: &Path) -> Result<(Vec<Certificate>, PrivateKey)>;
// 生成自签名证书
fn generate_self_signed() -> Result<(Certificate, PrivateKey)>;
}
config.rs
// 构建服务端 TLS 配置
pub fn build_server_config(certs: Vec<Certificate>, key: PrivateKey) -> Result<ServerConfig>;
// 构建客户端 TLS 配置(跳过证书验证)
pub fn build_client_config() -> Result<ClientConfig>;
6. Database 模块
SQLite 数据库操作。
schema.rs
// 初始化数据库表结构
pub fn init_database(conn: &Connection) -> Result<()>;
// 表结构:
// - chat_messages: 聊天消息
// - file_transfers: 文件传输记录
// - known_devices: 已知设备
// - app_settings: 应用设置
repository.rs
pub struct Database;
impl Database {
// 消息操作
pub fn save_message(message: &ChatMessage) -> Result<()>;
pub fn get_chat_history(device_id: &str, limit: usize, offset: usize) -> Result<Vec<ChatMessage>>;
// 传输操作
pub fn save_file_transfer(transfer: &FileTransfer) -> Result<()>;
pub fn update_transfer_progress(file_id: &str, progress: f64, ...) -> Result<()>;
pub fn get_transfer_history(device_id: &str, ...) -> Result<Vec<FileTransfer>>;
// 设备操作
pub fn save_known_device(device: &DeviceInfo) -> Result<()>;
pub fn get_known_devices() -> Result<Vec<DeviceInfo>>;
// 设置操作
pub fn get_setting(key: &str) -> Result<Option<String>>;
pub fn set_setting(key: &str, value: &str) -> Result<()>;
}
7. Models 模块
数据模型定义。
device.rs
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeviceInfo {
pub device_id: String, // UUID
pub device_name: String, // 显示名称
pub ip: String, // IP 地址
pub ws_port: u16, // WebSocket 端口
pub http_port: u16, // HTTP 端口
pub last_seen: i64, // 最后在线时间
}
message.rs
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChatMessage {
pub id: String,
pub from_device: String,
pub to_device: String,
pub content: String,
pub message_type: MessageType,
pub timestamp: i64,
pub is_read: bool,
}
file_transfer.rs
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileTransfer {
pub file_id: String,
pub name: String,
pub size: u64,
pub progress: f64,
pub status: TransferStatus,
pub mime_type: Option<String>,
pub from_device: String,
pub to_device: String,
pub local_path: Option<String>,
pub created_at: i64,
pub completed_at: Option<i64>,
pub transferred_bytes: u64,
}
pub enum TransferStatus {
Pending,
Transferring,
Completed,
Failed,
Cancelled,
}
events.rs
// 事件名称常量
pub mod event_names {
pub const DEVICE_FOUND: &str = "device:found";
pub const DEVICE_LOST: &str = "device:lost";
pub const CHAT_MESSAGE: &str = "chat:message";
pub const FILE_PROGRESS: &str = "file:progress";
}
// 传输进度事件
#[derive(Debug, Clone, Serialize)]
pub struct TransferProgressEvent {
pub file_id: String,
pub progress: f64,
pub transferred_bytes: u64,
pub total_bytes: u64,
pub status: TransferStatus,
pub file_name: Option<String>,
pub local_path: Option<String>,
}
8. State 模块
全局应用状态管理。
// 全局单例
static APP_STATE: OnceCell<Arc<AppStateInner>> = OnceCell::new();
pub struct AppStateInner {
pub local_device: RwLock<DeviceInfo>,
pub device_manager: DeviceManager,
pub discovery_service: RwLock<Option<DiscoveryService>>,
pub ws_server: RwLock<Option<WsServer>>,
pub ws_client: RwLock<Option<WsClient>>,
pub http_server: RwLock<Option<HttpServer>>,
pub http_client: HttpClient,
pub connection_manager: ConnectionManager,
pub app_data_dir: PathBuf,
pub transfer_cancellation_tokens: RwLock<HashMap<String, CancellationToken>>,
}
pub struct AppState;
impl AppState {
pub fn init(app_data_dir: PathBuf) -> Result<()>;
pub fn get() -> Arc<AppStateInner>;
}
错误处理
使用 thiserror 定义统一的错误类型:
#[derive(Debug, thiserror::Error)]
pub enum AppError {
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Database error: {0}")]
Database(#[from] rusqlite::Error),
#[error("WebSocket error: {0}")]
WebSocket(String),
#[error("TLS error: {0}")]
Tls(String),
#[error("File transfer error: {0}")]
FileTransfer(String),
#[error("{0}")]
General(String),
}
依赖关系
main.rs
└── lib.rs
├── commands/
│ ├── discovery_commands ──▶ discovery/, state
│ ├── chat_commands ──────▶ websocket/, database/, state
│ ├── file_commands ──────▶ http/, database/, state
│ └── config_commands ────▶ utils/, database/
├── state ──────────────────▶ models/, discovery/, websocket/, http/
└── database/ ──────────────▶ models/