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.

11 KiB

通信协议

本文档详细介绍 Flash Send 使用的网络通信协议。

概述

Flash Send 使用三种协议进行通信:

协议 端口 用途 加密
UDP 53317 设备发现
WebSocket 53318 即时聊天 无(局域网)
HTTPS 53319 文件传输 TLS

设备发现协议

广播机制

使用 UDP 广播在局域网内发现设备。

广播地址: 255.255.255.255:53317

广播频率: 每 3 秒一次

消息格式

所有消息使用 JSON 格式,以换行符 \n 结尾。

广播消息 (Announce)

设备向局域网广播自身信息:

{
  "type": "announce",
  "device": {
    "device_id": "550e8400-e29b-41d4-a716-446655440000",
    "device_name": "My Computer",
    "ip": "192.168.1.100",
    "ws_port": 53318,
    "http_port": 53319,
    "last_seen": 1701388800
  }
}

响应消息 (Response)

收到广播后,设备回复自身信息:

{
  "type": "response",
  "device": {
    "device_id": "661e9500-f30c-52e5-b827-557766551111",
    "device_name": "Other PC",
    "ip": "192.168.1.101",
    "ws_port": 53318,
    "http_port": 53319,
    "last_seen": 1701388805
  }
}

设备状态

  • 在线: 每 3 秒收到广播/响应
  • 离线: 超过 15 秒未收到任何消息

流程图

┌─────────────┐                              ┌─────────────┐
│  Device A   │                              │  Device B   │
└──────┬──────┘                              └──────┬──────┘
       │                                            │
       │  UDP Broadcast (announce)                  │
       │  255.255.255.255:53317                     │
       │ ─────────────────────────────────────────▶ │
       │                                            │
       │                      UDP Response          │
       │ ◀───────────────────────────────────────── │
       │                                            │
       │  Device A adds Device B to list            │
       │                                            │
       │                      Device B adds         │
       │                      Device A to list      │
       │                                            │

WebSocket 聊天协议

连接建立

  1. 客户端连接到目标设备的 WebSocket 服务
  2. 发送握手消息
  3. 服务端确认后,连接建立

连接地址: ws://{ip}:{ws_port}

消息格式

所有消息使用 JSON 格式。

握手消息 (Handshake)

客户端首先发送握手消息:

{
  "type": "handshake",
  "device_id": "550e8400-e29b-41d4-a716-446655440000",
  "device_name": "My Computer"
}

聊天消息 (Chat)

{
  "type": "chat",
  "message": {
    "id": "msg-uuid-12345",
    "from_device": "550e8400-e29b-41d4-a716-446655440000",
    "to_device": "661e9500-f30c-52e5-b827-557766551111",
    "content": "Hello, World!",
    "message_type": "text",
    "timestamp": 1701388800000
  }
}

message_type 枚举:

  • text: 普通文本
  • image: 图片content 为 base64 或路径)
  • file: 文件content 为文件名)
  • system: 系统消息

确认消息 (Ack)

{
  "type": "ack",
  "message_id": "msg-uuid-12345"
}

心跳消息 (Ping/Pong)

{
  "type": "ping"
}
{
  "type": "pong"
}

连接管理

  • 心跳间隔: 30 秒
  • 超时断开: 90 秒无响应
  • 自动重连: 断开后尝试重连

流程图

┌─────────────┐                              ┌─────────────┐
│   Client    │                              │   Server    │
└──────┬──────┘                              └──────┬──────┘
       │                                            │
       │  WebSocket Connect                         │
       │ ─────────────────────────────────────────▶ │
       │                                            │
       │  Handshake                                 │
       │ ─────────────────────────────────────────▶ │
       │                                            │
       │                          Connection OK     │
       │ ◀───────────────────────────────────────── │
       │                                            │
       │  Chat Message                              │
       │ ─────────────────────────────────────────▶ │
       │                                            │
       │                          Ack               │
       │ ◀───────────────────────────────────────── │
       │                                            │
       │  Ping                                      │
       │ ─────────────────────────────────────────▶ │
       │                                            │
       │                          Pong              │
       │ ◀───────────────────────────────────────── │
       │                                            │

HTTPS 文件传输协议

TLS 配置

  • 证书类型: 自签名 RSA 2048
  • 证书有效期: 365 天
  • 客户端验证: 跳过(局域网内互信)

端点

POST /upload

上传文件到服务端。

Content-Type: multipart/form-data

表单字段:

字段 类型 说明
file_id string 文件传输 ID
from_device string 发送方设备 ID
file binary 文件内容

请求示例:

POST /upload HTTP/1.1
Host: 192.168.1.100:53319
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Length: 12345

------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file_id"

550e8400-e29b-41d4-a716-446655440000
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="from_device"

661e9500-f30c-52e5-b827-557766551111
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file"; filename="document.pdf"
Content-Type: application/pdf

<binary data>
------WebKitFormBoundary7MA4YWxkTrZu0gW--

响应:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "success": true,
  "file_id": "550e8400-e29b-41d4-a716-446655440000",
  "file_name": "document.pdf",
  "file_size": 12345
}

GET /download/{file_id}

从服务端下载文件(预留接口)。

传输流程

┌─────────────┐                              ┌─────────────┐
│   Sender    │                              │  Receiver   │
└──────┬──────┘                              └──────┬──────┘
       │                                            │
       │  1. Create FileTransfer record             │
       │     (status: pending)                      │
       │                                            │
       │  2. TLS Handshake                          │
       │ ─────────────────────────────────────────▶ │
       │                                            │
       │  3. POST /upload (multipart)               │
       │ ─────────────────────────────────────────▶ │
       │     [chunk 1]                              │
       │     emit progress event                    │
       │ ─────────────────────────────────────────▶ │
       │     [chunk 2]                              │  4. Save to disk
       │     emit progress event                    │     emit progress event
       │ ─────────────────────────────────────────▶ │
       │     [chunk n]                              │
       │     emit progress event                    │
       │                                            │
       │                          HTTP 200 OK       │
       │ ◀───────────────────────────────────────── │
       │                                            │
       │  5. Update status: completed               │  5. Update status: completed
       │     emit final progress event              │     emit final progress event
       │                                            │

分块传输

大文件使用分块传输,每块大小为 64KB

进度计算:

progress = transferred_bytes / total_bytes

进度事件:

  • 每发送一个块后触发
  • 包含当前进度、已传输字节数、总字节数

取消机制

  1. 发送方调用 cancel_transfer
  2. 触发 CancellationToken
  3. 上传循环检测到取消,中断传输
  4. 更新状态为 cancelled
  5. 发送进度事件通知前端

安全考虑

局域网信任模型

Flash Send 假设局域网内的设备是可信的:

  • UDP 广播不加密(仅设备发现)
  • WebSocket 不加密(聊天内容)
  • HTTP 使用 TLS文件传输

TLS 证书

  • 应用首次启动时生成自签名证书
  • 证书存储在用户数据目录
  • 客户端跳过证书验证(dangerous_configuration

建议

如果需要更高安全性:

  1. 添加设备配对/授权机制
  2. 使用端到端加密
  3. 添加消息签名验证

端口冲突处理

如果默认端口被占用:

  1. 检测: 启动时检查端口可用性
  2. 提示: 通知用户端口冲突
  3. 配置: 允许用户在设置中修改端口

端口范围建议: 53317 - 53399