refactor: 收口为hub/peer/bridge 三程序并统一 支持 tcp/udp/kcp"
This commit is contained in:
435
README.md
435
README.md
@@ -1,274 +1,213 @@
|
||||
# OmniSocket
|
||||
|
||||
统一的 TCP / UDP / KCP 传输框架,包含:
|
||||
- 协议抽象层(`omni_init / omni_send / omni_recv`)
|
||||
- 客户端:文件分片发送 + 异步接收服务端 ASCII 指令
|
||||
- 服务端:接收并写文件 + 交互输入指令下发客户端
|
||||
- 转发器:A->B 中转,支持运行时动态修改目标端口
|
||||
- Hub:云端多客户端注册/绑定/路由,支持 A ↔ C ↔ B 命令透传
|
||||
- Peer:主动连接 Hub 的对等端,支持 `register / bind / send / say`
|
||||
- 启动前时钟同步:客户端先测 `RTT + offset`,服务端据此输出补偿后的端到端时延
|
||||
OmniSocket 当前包含 3 个核心程序:
|
||||
- `omni_peer`
|
||||
- `omni_hub`
|
||||
- `omni_bridge`
|
||||
|
||||
## 目录结构
|
||||
|
||||
```text
|
||||
OmniSocket/
|
||||
├── include/
|
||||
│ ├── common.h # MsgHeader(type,len,timestamp)、消息类型、通用宏
|
||||
│ ├── network.h # 统一协议接口定义
|
||||
│ ├── kcp/ikcp.h # KCP 头文件
|
||||
│ └── logger.h # 日志与统计接口
|
||||
├── src/
|
||||
│ ├── protocols/
|
||||
│ │ ├── tcp_impl.c # TCP 实现(16字节头 + 粘包拆包)
|
||||
│ │ ├── udp_impl.c # UDP 实现(sendto/recvfrom)
|
||||
│ │ ├── kcp_impl.c # KCP 实现(基于 UDP + ikcp)
|
||||
│ │ └── ikcp.c # KCP 源码
|
||||
│ ├── core/
|
||||
│ │ ├── network.c # 协议工厂分发
|
||||
│ │ └── logger.c # 性能统计日志
|
||||
│ └── apps/
|
||||
│ ├── client_main.c # 客户端入口
|
||||
│ ├── hub_main.c # Hub 入口(多客户端注册/路由)
|
||||
│ ├── peer_main.c # Peer 入口(连接 Hub 的对等端)
|
||||
│ ├── server_main.c # 服务端入口
|
||||
│ ├── relay_main.c # 转发器入口
|
||||
│ └── test_main.c # 简易协议连通性测试
|
||||
├── scripts/
|
||||
│ └── local_smoke_test.sh # 本机一键 smoke 测试
|
||||
├── build/ # 编译产物目录
|
||||
├── Makefile
|
||||
└── README.md
|
||||
```
|
||||
三者统一支持 `tcp | udp | kcp` 三种传输协议。
|
||||
|
||||
## 构建
|
||||
|
||||
### 本机构建
|
||||
本地构建:
|
||||
|
||||
```bash
|
||||
make
|
||||
```
|
||||
|
||||
生成:
|
||||
- `build/omni_client`
|
||||
- `build/omni_hub`
|
||||
生成文件:
|
||||
- `build/omni_peer`
|
||||
- `build/omni_server`
|
||||
- `build/omni_relay`
|
||||
- `build/omni_test`
|
||||
- `build/omni_hub`
|
||||
- `build/omni_bridge`
|
||||
|
||||
### ARM 交叉编译
|
||||
|
||||
默认使用 `arm-linux-gnueabihf-gcc`:
|
||||
Jetson 场景常用 ARM64 交叉编译:
|
||||
|
||||
```bash
|
||||
make arm
|
||||
make arm64
|
||||
```
|
||||
|
||||
生成到 `build/arm/` 目录。
|
||||
生成文件:
|
||||
- `build/arm64/omni_peer`
|
||||
- `build/arm64/omni_hub`
|
||||
- `build/arm64/omni_bridge`
|
||||
|
||||
## 程序参数
|
||||
|
||||
### `omni_server`
|
||||
|
||||
```bash
|
||||
build/omni_server -p tcp|udp|kcp -P <listen_port> -o <output_file> [-b <bind_ip>]
|
||||
```
|
||||
|
||||
说明:
|
||||
- 接收客户端发送的文件分片并写入 `output_file`
|
||||
- 若在交互终端运行,可在标准输入输入 ASCII 文本并回发给客户端
|
||||
- 输入 `quit` 可退出服务端交互循环
|
||||
|
||||
### `omni_client`
|
||||
|
||||
```bash
|
||||
build/omni_client -p tcp|udp|kcp -H <server_ip> -P <server_port> -f <file> [-b <bind_port>] [-m <chunk_mtu>] [-w <wait_seconds|-1>]
|
||||
```
|
||||
|
||||
说明:
|
||||
- 读取 `file`,按 `chunk_mtu`(默认 1400)分片发送
|
||||
- 发送结束后额外发送 `FILE_END` 控制包
|
||||
- 后台线程持续接收并打印服务端 ASCII 指令
|
||||
- `-w -1` 表示常驻模式,直到手动 `Ctrl+C`
|
||||
- 建连后会先自动发送 `TIME_SYNC_REQ/RESP/REPORT`,以最小 RTT 样本估算 `server_time - client_time`
|
||||
- 若同步响应不可达(例如经过当前实现的单向 relay),文件传输仍继续,但服务端不会产出补偿后的 `end_to_end_delay_ms`
|
||||
|
||||
### `omni_relay`
|
||||
|
||||
```bash
|
||||
build/omni_relay -p tcp|udp|kcp -L <listen_port> -H <target_ip> -P <target_port>
|
||||
```
|
||||
|
||||
标准输入支持命令:
|
||||
- `set <ip> <port>`:动态修改转发目标
|
||||
- `show`:显示当前目标
|
||||
- `quit`:退出 relay
|
||||
|
||||
### `omni_hub`
|
||||
|
||||
```bash
|
||||
build/omni_hub -P <listen_port> [-b <bind_ip>] [-p tcp]
|
||||
```
|
||||
|
||||
说明:
|
||||
- 当前阶段只实现 TCP 控制面
|
||||
- 多个 `omni_peer` 主动连接到 hub 后,先用 `client_id` 注册
|
||||
- hub 维护 `client_id -> socket` 映射,并按 `dst_id` 转发 `PEER_TUNNEL`
|
||||
## 程序说明
|
||||
|
||||
### `omni_peer`
|
||||
|
||||
`omni_peer` 支持两种工作模式:
|
||||
- `hub` 模式:连接 `hub` 或 `bridge`
|
||||
- `direct` 模式:`peer` 之间直接互连
|
||||
|
||||
常见用途:
|
||||
- 发送文本命令
|
||||
- 发送文件
|
||||
- 接收文件
|
||||
|
||||
### `omni_hub`
|
||||
|
||||
`omni_hub` 是中心注册与转发节点,通常部署在公网服务器或中心网络位置。
|
||||
|
||||
主要职责:
|
||||
- 维护 `client_id -> session`
|
||||
- 转发 `peer` 之间的 `bind / tunnel / status`
|
||||
|
||||
### `omni_bridge`
|
||||
|
||||
`omni_bridge` 是桥接节点,用于将远端 `peer` 接入上游 `hub`。
|
||||
|
||||
主要职责:
|
||||
- 上游连接 `hub`
|
||||
- 下游监听本地入口供 `peer` 接入
|
||||
- 适用于 `A <-> C <-> D <-> B` 这类桥接链路
|
||||
|
||||
当前限制:
|
||||
- 一个 `bridge` 仅支持一个下游 `peer`
|
||||
- 下游 `peer` 的 `-i` 必须与 `bridge -i` 保持一致
|
||||
- 上下游必须使用同一种协议,不支持协议转换
|
||||
- 当前实现更接近“单下游、单身份桥接”,而不是通用多租户中继
|
||||
|
||||
## 角色说明
|
||||
|
||||
- `A`:本地电脑
|
||||
- `B`:Jetson
|
||||
- `C`:公网 Hub 服务器
|
||||
- `D`:公网 Bridge 服务器
|
||||
|
||||
下面示例中的 `<proto>` 可替换为 `tcp`、`udp` 或 `kcp`。
|
||||
|
||||
说明:
|
||||
- 以下 `omni_peer` 示例统一采用长连接交互模式
|
||||
- 启动后连接会保持,不再使用“传输一次后自动退出”的一次性写法
|
||||
- 文本和文件传输通过终端中的交互命令完成
|
||||
- 若启动命令中使用了 `-m` 或 `-F`,程序会执行启动动作模式,而不是进入当前 README 使用的交互模式
|
||||
|
||||
## 常用参数与命令
|
||||
|
||||
| 分类 | 写法 | 含义 |
|
||||
| --- | --- | --- |
|
||||
| 启动参数 | `-i <client_id>` | 当前 `peer` 的逻辑身份。Hub 会根据这个 ID 记录 `client_id -> session` 映射,例如 `-i pc` 表示“我是 pc”,`-i jetson` 表示“我是 jetson”。 |
|
||||
| 启动参数 | `-b <peer_id>` | 启动后默认绑定的目标 `peer`。例如 `-b jetson` 表示后续直接输入 `send ...` 或 `put ...` 时,默认发给 `jetson`。 |
|
||||
| 启动参数 | `-d <peer_id>` | 启动动作模式下的显式目标。通常与 `-m` 或 `-F` 配合使用,表示把启动时的那条消息或那个文件直接发给指定目标。 |
|
||||
| 启动参数 | `-o <output_file>` | 本地接收文件时的落盘路径。收到文件后会写入当前机器上的这个路径,例如 `-o /tmp/from_pc.bin`。 |
|
||||
| 交互命令 | `bind <peer_id>` | 将默认目标切换到指定 `peer`,后续 `send` 或 `put` 默认发给它。 |
|
||||
| 交互命令 | `send <text>` | 向当前默认目标发送一条文本消息。 |
|
||||
| 交互命令 | `say <peer_id> <text>` | 向指定 `peer` 发送一条文本消息,不修改当前默认目标。 |
|
||||
| 交互命令 | `put <file>` | 将当前机器上的文件发送给当前默认目标。 |
|
||||
| 交互命令 | `push <peer_id> <file>` | 将当前机器上的文件发送给指定 `peer`,不修改当前默认目标。 |
|
||||
| 交互命令 | `show` | 显示当前本地状态,例如 `client_id`、当前绑定目标和输出路径。 |
|
||||
| 交互命令 | `quit` | 退出当前 `omni_peer` 进程。 |
|
||||
|
||||
## 场景 1:点对点直传
|
||||
|
||||
`A <-> B`
|
||||
|
||||
B 端监听:
|
||||
|
||||
```bash
|
||||
build/omni_peer -H <hub_ip> -P <hub_port> -i <client_id> [-b <peer_id>] [-d <peer_id>] [-m <text>] [-w <wait_seconds|-1>]
|
||||
./build/omni_peer -M direct -p <proto> -L 9001 -i jetson -o /tmp/from_pc.bin
|
||||
```
|
||||
|
||||
A 端连接:
|
||||
|
||||
```bash
|
||||
./build/omni_peer -M direct -p <proto> -H <B_IP> -P 9001 -i pc -b jetson -o /tmp/from_jetson.bin
|
||||
```
|
||||
|
||||
连接建立后,可在 A 端输入:
|
||||
|
||||
```text
|
||||
send start
|
||||
put /tmp/input.bin
|
||||
```
|
||||
|
||||
如需反向 `B -> A`,可在 B 端输入:
|
||||
|
||||
```text
|
||||
put /path/to/file.bin
|
||||
```
|
||||
|
||||
## 场景 2:通过 Hub 中转
|
||||
|
||||
`A <-> C <-> B`
|
||||
|
||||
C 端启动 Hub:
|
||||
- C 维护着一张 `client_id -> session` 映射表,用于记录谁是 `pc`、谁是 `jetson`,并据此转发 `bind / tunnel / status`
|
||||
|
||||
```bash
|
||||
./build/omni_hub -p <proto> -P 9002
|
||||
```
|
||||
|
||||
B 端连接 Hub:
|
||||
|
||||
```bash
|
||||
./build/omni_peer -p <proto> -H <C_IP> -P 9002 -i jetson -o /tmp/from_pc.bin
|
||||
```
|
||||
|
||||
A 端连接 Hub:
|
||||
|
||||
```bash
|
||||
./build/omni_peer -p <proto> -H <C_IP> -P 9002 -i pc -b jetson -o /tmp/from_jetson.bin
|
||||
```
|
||||
|
||||
连接建立后,可在 A 端输入:
|
||||
|
||||
```text
|
||||
send start
|
||||
put /tmp/input.bin
|
||||
```
|
||||
|
||||
如需反向 `B -> A`,可在 B 端输入:
|
||||
|
||||
```text
|
||||
bind pc
|
||||
put /path/to/file.bin
|
||||
```
|
||||
|
||||
## 场景 3:通过 Bridge 桥接
|
||||
|
||||
`A <-> C <-> D <-> B`
|
||||
|
||||
C 端启动 Hub:
|
||||
- C 仍然维护 `client_id -> session` 映射表;A 以 `pc` 注册到 C,Bridge 以 `jetson` 这个逻辑身份注册到 C
|
||||
|
||||
```bash
|
||||
./build/omni_hub -p <proto> -P 9003
|
||||
```
|
||||
|
||||
D 端启动 Bridge:
|
||||
|
||||
```bash
|
||||
./build/omni_bridge -p <proto> -H <C_IP> -P 9003 -i jetson -L 9004
|
||||
```
|
||||
|
||||
B 端连接 Bridge:
|
||||
|
||||
```bash
|
||||
./build/omni_peer -p <proto> -H <D_IP> -P 9004 -i jetson -o /tmp/from_pc.bin
|
||||
```
|
||||
|
||||
A 端连接 Hub:
|
||||
|
||||
```bash
|
||||
./build/omni_peer -p <proto> -H <C_IP> -P 9003 -i pc -b jetson -o /tmp/from_jetson.bin
|
||||
```
|
||||
|
||||
连接建立后,可在 A 端输入:
|
||||
|
||||
```text
|
||||
send start
|
||||
put /tmp/input.bin
|
||||
```
|
||||
|
||||
如需反向 `B -> A`,可在 B 端输入:
|
||||
|
||||
```text
|
||||
bind pc
|
||||
put /path/to/file.bin
|
||||
```
|
||||
|
||||
说明:
|
||||
- `-i`:当前 peer 的逻辑 ID,后续所有路由都依赖它,不依赖私网 IP
|
||||
- `-b`:启动后先请求绑定默认目标
|
||||
- `-m`:启动后立即发一条命令;若同时给了 `-d`,则直接发给该目标
|
||||
- `-w`:one-shot 模式下等待若干秒再退出,`-1` 表示常驻
|
||||
- 该场景已经实现 `A -> C -> D -> B` 与 `B -> D -> C -> A` 的桥接转发
|
||||
- 但当前 `bridge` 仍是单下游、单身份模型,不是完整的多节点桥接网络
|
||||
|
||||
交互命令:
|
||||
- `bind <peer_id>`:绑定默认目标
|
||||
- `send <text>`:发给当前绑定目标
|
||||
- `say <peer_id> <text>`:显式指定目标
|
||||
- `show`:显示本地 `client_id / bound_peer`
|
||||
- `quit`:退出
|
||||
|
||||
## 快速启动(本机)
|
||||
|
||||
先准备一个测试文件:
|
||||
|
||||
```bash
|
||||
dd if=/dev/urandom of=/tmp/input.bin bs=1400 count=64
|
||||
```
|
||||
|
||||
### TCP 直连(2 个终端)
|
||||
|
||||
终端 1:
|
||||
|
||||
```bash
|
||||
build/omni_server -p tcp -P 9000 -o /tmp/out_tcp.bin
|
||||
```
|
||||
|
||||
终端 2:
|
||||
|
||||
```bash
|
||||
build/omni_client -p tcp -H 127.0.0.1 -P 9000 -f /tmp/input.bin
|
||||
```
|
||||
|
||||
校验:
|
||||
|
||||
```bash
|
||||
cmp -s /tmp/input.bin /tmp/out_tcp.bin && echo OK || echo FAIL
|
||||
```
|
||||
|
||||
日志观察:
|
||||
- client / server 的 `summary` 日志会新增 `clock_sync_ok`、`clock_offset_ms`、`clock_sync_rtt_ms`、`clock_sync_samples`
|
||||
- server 侧的 `end_to_end_avg_ms` 在 `clock_sync_ok=1` 时表示已经按 offset 补偿后的端到端时延
|
||||
|
||||
### UDP 直连(2 个终端)
|
||||
|
||||
终端 1:
|
||||
|
||||
```bash
|
||||
build/omni_server -p udp -P 9001 -o /tmp/out_udp.bin
|
||||
```
|
||||
|
||||
终端 2:
|
||||
|
||||
```bash
|
||||
build/omni_client -p udp -H 127.0.0.1 -P 9001 -f /tmp/input.bin
|
||||
```
|
||||
|
||||
校验:
|
||||
|
||||
```bash
|
||||
cmp -s /tmp/input.bin /tmp/out_udp.bin && echo OK || echo FAIL
|
||||
```
|
||||
|
||||
### KCP 直连(2 个终端)
|
||||
|
||||
终端 1:
|
||||
|
||||
```bash
|
||||
build/omni_server -p kcp -P 9002 -o /tmp/out_kcp.bin
|
||||
```
|
||||
|
||||
终端 2:
|
||||
|
||||
```bash
|
||||
build/omni_client -p kcp -H 127.0.0.1 -P 9002 -f /tmp/input.bin
|
||||
```
|
||||
|
||||
校验:
|
||||
|
||||
```bash
|
||||
cmp -s /tmp/input.bin /tmp/out_kcp.bin && echo OK || echo FAIL
|
||||
```
|
||||
|
||||
## Relay 场景示例(3 个终端)
|
||||
|
||||
终端 1(最终接收端 B):
|
||||
|
||||
```bash
|
||||
build/omni_server -p udp -P 9102 -o /tmp/out_relay.bin
|
||||
```
|
||||
|
||||
终端 2(relay):
|
||||
|
||||
```bash
|
||||
build/omni_relay -p udp -L 9101 -H 127.0.0.1 -P 9102
|
||||
```
|
||||
|
||||
终端 3(发送端 A):
|
||||
|
||||
```bash
|
||||
build/omni_client -p udp -H 127.0.0.1 -P 9101 -f /tmp/input.bin
|
||||
```
|
||||
|
||||
relay 终端可输入:
|
||||
|
||||
```text
|
||||
show
|
||||
set 127.0.0.1 9103
|
||||
```
|
||||
|
||||
## Hub / Peer 场景(3 个终端)
|
||||
|
||||
终端 1(cloud hub C):
|
||||
|
||||
```bash
|
||||
build/omni_hub -P 9200
|
||||
```
|
||||
|
||||
终端 2(peer B):
|
||||
|
||||
```bash
|
||||
build/omni_peer -H 127.0.0.1 -P 9200 -i beta
|
||||
```
|
||||
|
||||
终端 3(peer A):
|
||||
|
||||
```bash
|
||||
build/omni_peer -H 127.0.0.1 -P 9200 -i alpha
|
||||
```
|
||||
|
||||
在 A 终端输入:
|
||||
|
||||
```text
|
||||
bind beta
|
||||
send hello-from-alpha
|
||||
```
|
||||
|
||||
此时 B 终端会打印:
|
||||
|
||||
```text
|
||||
[peer alpha -> beta] hello-from-alpha
|
||||
```
|
||||
|
||||
本地一键 smoke:
|
||||
|
||||
```bash
|
||||
./scripts/local_peer_smoke_test.sh
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user