更新记录

1.0.0(2026-06-18) 下载此版本

  • 作为 1.0.0 起始版本,初始化 jz-webrtc-connect 通用 WebRTC DataChannel 通讯插件,面向 uni-appH5 / App 场景。
  • 提供统一 SDK 入口,支持通过 configure() 保存低频基础配置,并通过 connect() 发起真实建连。
  • 内置 host / client 双角色模型,支持房间式实时通讯、单播、Host 广播、心跳保活、ACK、请求响应与客户端自动重连。
  • 支持 PeerJS 信令模式,适合快速接入已有 PeerServer 的项目。
  • 支持 native 信令模式,可通过 WebSocket 或自定义 transport 交换 offer / answer / candidate,服务端仅需负责按 roomIdto 转发信令消息。
  • 支持 custom adapter 扩展入口,便于业务方复用插件上层通讯核心,同时接入自定义信令体系。
  • 提供可选数据同步模块 DataCore,支持 kv / list / map 三类命名空间容器,以及 Host 权威数据源下的 patch / snapshot 同步机制。
  • 提供基础持久化驱动抽象,内置内存驱动与 uni storage 驱动,方便业务按需扩展。
  • 提供 renderjs 桥接组件骨架,便于后续 App 侧扩展。
  • 补充详细文档,重点说明插件用法、配置项、信令模式差异,以及 WebRTC 相比纯 WebSocket 在“打洞成功后业务数据不走服务器、节约带宽与中转资源”方面的优势与边界。

平台兼容性

uni-app(4.74)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
- - -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
× × × × × × × × × × × ×

jz-webrtc-connect

jz-webrtc-connect1.0.0 版本开始,是一个面向 uni-app 的通用 WebRTC DataChannel 通讯插件,支持 H5 / App,用于构建房间协作、实时指令同步、局域网或互联网点对点消息传输等场景。

它聚焦的是“数据通讯”而不是音视频 UI:

  • 提供统一的连接核心 ConnectCore
  • 支持 PeerJSnative WebSocket 信令custom adapter
  • 提供可选的数据同步层 DataCore
  • 支持 host / client 双角色模型
  • 支持心跳、ACK、请求响应、客户端重连、Host 广播

为什么它比纯 WebSocket 更省资源

很多实时业务一开始会直接上 WebSocket,但纯 WebSocket 有一个天然问题:

  • 所有业务数据都必须经过服务器转发
  • 房间人数一多,服务端带宽、连接数、转发 CPU、内存压力都会持续上升
  • 每条消息都要走“客户端 -> 服务器 -> 客户端”,延迟路径更长

jz-webrtc-connect 的核心优势在于:

  • WebSocket 或 PeerServer 主要只负责“信令交换”
  • 真正的业务消息走 WebRTC DataChannel
  • 在 NAT 打洞成功时,数据直接在终端之间传输,不经过业务服务器
  • 服务器不再承担高频业务包转发,资源占用明显更低

可以简单理解为:

  • 纯 WebSocket:服务器既负责建链,也负责所有数据中转
  • WebRTC DataChannel:服务器主要负责“介绍双方认识”,连通后数据尽量点对点直达

这意味着在打洞成功后,你可以获得这些收益:

  • 节约服务器带宽
  • 降低消息中转成本
  • 降低服务端并发转发压力
  • 降低中心节点故障对业务消息面的影响
  • 在很多场景下得到更低的传输延迟

重要边界

请务必正确理解 WebRTC 的工作边界:

  • signal 依然是必须的,建连前必须交换 offer / answer / candidate
  • native 模式里通常使用 WebSocket 做信令
  • peerjs 模式里由 PeerServer 帮你完成信令交换
  • 如果网络环境复杂,可能需要 TURN 中继
  • 一旦退化到 TURN,中继流量会经过 TURN 服务器,不再是完全点对点

所以更准确的表述是:

在 STUN / NAT 打洞成功时,业务数据可绕过业务服务器直连传输;如果必须依赖 TURN,则数据会经过 TURN 中继。

典型场景

  • 实时房间控制指令同步
  • 多端协作状态同步
  • 局域网点对点通讯
  • 轻量级实时消息广播
  • 低频信令 + 高频业务数据的拆分架构

插件结构分析

src/uni_modules/jz-webrtc-connect 目录大致分为四层:

1. 入口层

  • js_sdk/jz-webrtc-connect/index.js

对外暴露统一 API:

  • configure() 保存低频基础配置
  • connect() 发起一次真实建连
  • getInstance() 获取当前连接核心
  • destroy() 销毁当前连接
  • createDataCore() 创建可选数据同步层

2. 连接层

  • connect/ConnectCore.js
  • connect/HostPeerLink.js
  • connect/ClientPeerLink.js
  • connect/PeerLinkBase.js
  • connect/HeartbeatMonitor.js
  • connect/MessageCodec.js

职责是:

  • 根据角色创建 hostclient 链路
  • 管理 DataChannel 生命周期
  • 提供 send / broadcast / request / kick
  • 处理心跳、ACK、请求响应、重连等基础能力

3. 信令适配层

  • connect/adapters/PeerJSSignalAdapter.js
  • connect/adapters/NativeSignalAdapter.js
  • connect/adapters/SignalAdapterBase.js
  • connect/adapters/NativeDataConnection.js

职责是:

  • 负责建连前的信令交换
  • 对上层输出统一 DataConnection 接口
  • 屏蔽 PeerJS 与原生 RTCPeerConnection 的差异

4. 数据同步层

  • data/DataCore.js
  • data/ReplicationManager.js
  • data/KeyValueStore.js
  • data/ListStore.js
  • data/MapStore.js
  • data/StorageDriver.js

职责是:

  • 基于通讯核心做房间数据同步
  • Host 作为权威数据源
  • Client 通过 patch 或 snapshot 跟随同步
  • 支持 kv / list / map 三种命名空间数据容器

基础用法

推荐把“低频基础配置”和“高频业务参数”分开:

  • configure():保存不常变化的基础配置,例如信令地址、ICE 配置、重连策略
  • connect():传入每次连接都可能变化的参数,例如 roleroomId

1. 导入

import jzWebrtcConnect from '@/uni_modules/jz-webrtc-connect/js_sdk/jz-webrtc-connect'

2. 初始化基础配置

await jzWebrtcConnect.configure({
  signal: {
    adapter: 'peerjs',
    peerjs: {
      host: 'peer.example.com',
      port: 443,
      path: '/peerjs',
      secure: true
    }
  },
  rtcConfig: {
    iceServers: [
      { urls: 'stun:stun.qq.com:3478' },
      { urls: 'stun:stun.aliyun.com:3478' }
    ]
  },
  reconnect: {
    enabled: true,
    maxAttempts: 5,
    baseDelayMs: 1000,
    factor: 2,
    maxDelayMs: 16000
  }
})

3. Host 创建房间

const core = await jzWebrtcConnect.connect({
  role: 'host',
  roomId: 'room-001'
})

core.on('ready', event => {
  console.log('host ready', event.peerId)
})

core.on('peer-join', event => {
  console.log('peer joined', event.peerId)
})

core.on('message', event => {
  console.log('message', event)
})

4. Client 加入房间

const core = await jzWebrtcConnect.connect({
  role: 'client',
  roomId: 'room-001'
})

core.on('ready', event => {
  console.log('client ready', event.peerId)
})

消息发送用法

1. 单播消息

await core.send('peer-xxx', 'chat', {
  type: 'text',
  payload: { text: 'hello' }
})

如果你不想自己写 type / payload 结构,也可以直接传业务对象:

await core.send('peer-xxx', 'chat', { text: 'hello' })

这时内部会自动转成:

{ type: 'msg', payload: { text: 'hello' } }

2. ACK 确认

const result = await core.send('peer-xxx', 'chat', { text: 'need ack' }, {
  ack: true,
  timeoutMs: 5000
})

console.log(result.acked)

3. Host 广播

只有 host 可以调用 broadcast()

await core.broadcast('room', {
  type: 'notice',
  payload: { text: 'game start' }
})

4. 请求响应

发起方:

const result = await core.request('peer-xxx', 'biz', {
  action: 'get-profile'
})

console.log(result)

接收方:

core.on('request', event => {
  if (event.channel !== 'biz') return
  event.respond({
    id: 1,
    name: 'demo-user'
  })
})

数据同步层用法

如果你不只是收发消息,还希望同步一份房间内共享数据,可以创建 DataCore

const core = await jzWebrtcConnect.connect({
  role: 'host',
  roomId: 'room-001'
})

const data = jzWebrtcConnect.createDataCore({ core })
const roomStore = data.namespace('room', 'kv')

roomStore.set('status', 'open')
roomStore.set('round', 1)

支持的数据容器

  • kv:键值对象,适合房间状态、配置项
  • list:列表容器,适合成员队列、聊天记录
  • map:映射容器,适合按主键存储复杂结构

可选持久化

默认使用内存驱动,也可以切换为 UniStorageDriver

import jzWebrtcConnect, { UniStorageDriver } from '@/uni_modules/jz-webrtc-connect/js_sdk/jz-webrtc-connect'

const data = jzWebrtcConnect.createDataCore({ core, autoPersist: true })
data.use(new UniStorageDriver('demo-room:'))

配置项说明

下面按实际源码能力说明常用配置项。

configure(baseConfig)

低频基础配置,内部只缓存,不会立即建连。

connect(sessionConfig)

会把 sessionConfig 与此前 configure() 的配置做合并,然后真正创建连接。

顶层配置

配置项 类型 默认值 说明
role 'host' \| 'client' 必填,当前节点角色
roomId string 房间 ID;peerjs 模式下 Host 默认会把它作为 peerId
peerId string 自动生成或由适配器生成 当前节点自定义 ID
hostPeerId string roomId Client 连接的 Host peerId;不传时通常回退到 roomId
maxClients number 8 Host 最大接入人数
handshakeTimeoutMs number 15000 DataChannel 握手超时毫秒数
heartbeatIntervalMs number 5000 心跳发送间隔
heartbeatMissThreshold number 3 连续丢失多少次心跳判定离线
codec string 'json' 消息编解码方式
rtcConfig RTCConfiguration {} WebRTC ICE 配置
reconnect object 见下文 Client 重连策略
relay object { enabled: true, includeSender: true } Host 是否把客户端消息继续转发给房间其他成员
signal object { adapter: 'peerjs' } 信令适配器配置

rtcConfig

这是 WebRTC 能否成功直连的关键配置之一,通常至少需要配置 iceServers

rtcConfig: {
  iceServers: [
    { urls: 'stun:stun.qq.com:3478' },
    { urls: 'stun:stun.aliyun.com:3478' },
    {
      urls: 'turn:turn.example.com:3478',
      username: 'demo',
      credential: 'demo-password'
    }
  ]
}

说明:

  • STUN 用于探测公网候选地址,帮助打洞
  • TURN 用于复杂网络下的中继兜底
  • 如果你非常强调“打洞成功后不走服务器”,就必须重视 STUN/TURN 配置质量
  • 公共 STUN 仅适合测试,生产环境建议自建或购买稳定 TURN 服务

reconnect

仅客户端侧有效:

配置项 类型 默认值 说明
enabled boolean true Host 断开后是否自动重连
maxAttempts number 5 最大重试次数
baseDelayMs number 1000 首次重连延迟
factor number 2 指数退避倍数
maxDelayMs number 16000 最大重连延迟

relay

Host 收到客户端业务消息后,可继续通过 WebRTC 数据通道转发给房间其他客户端:

配置项 类型 默认值 说明
enabled boolean true 是否开启消息转发
includeSender boolean true 转发时是否包含原发送者

注意:

  • 这里的“转发”发生在房主节点 host
  • 它依然不经过中心业务服务器
  • 适合一个房主带多个成员的房间式架构

signal 配置说明

1. peerjs 模式

适合:

  • 希望快速接入
  • 已有 PeerServer
  • 不想自己处理 offer / answer / candidate

示例:

await jzWebrtcConnect.configure({
  signal: {
    adapter: 'peerjs',
    peerjs: {
      host: 'peer.example.com',
      port: 443,
      path: '/peerjs',
      secure: true
    }
  },
  rtcConfig: {
    iceServers: [{ urls: 'stun:stun.qq.com:3478' }]
  }
})

signal.peerjs 会透传给 PeerJS 构造配置,常见字段包括:

配置项 说明
host PeerServer 域名或 IP
port PeerServer 端口
path PeerServer 路径
secure 是否使用 HTTPS / WSS
其他 PeerJS 支持字段 会一起透传给 PeerJS

说明:

  • PeerJS 负责的是信令和 DataConnection 封装
  • WebRTC 的 STUN / TURN 仍然由 rtcConfig 决定
  • Host 若未手动传 peerId,默认会优先使用 roomId

2. native 模式

适合:

  • 自己掌控信令服务器
  • 希望完全使用原生 RTCPeerConnection
  • 想把信令与业务数据彻底分离

示例:

await jzWebrtcConnect.configure({
  signal: {
    adapter: 'native',
    native: {
      url: 'wss://signal.example.com/ws',
      token: 'login-token'
    }
  },
  rtcConfig: {
    iceServers: [
      { urls: 'stun:stun.qq.com:3478' },
      { urls: 'stun:stun.aliyun.com:3478' }
    ]
  }
})

const core = await jzWebrtcConnect.connect({
  role: 'client',
  roomId: 'room-001'
})

signal.native 配置项:

配置项 类型 说明
url string WebSocket 信令服务地址
token string 可选认证字段,发送信令时会自动附带
transport object 自定义传输对象,优先级高于 url
hostPeerId string 可选,Client 未显式传远端时的默认 Host peerId

native 模式服务端需要做什么

服务端逻辑非常轻:

  • roomId 区分房间
  • to 定向转发信令包
  • 无需理解 SDP 内容
  • 无需转发业务数据

插件内部会处理的信令类型包括:

  • host-ready
  • join
  • offer
  • answer
  • candidate
  • leave

也就是说,WebSocket 在这个架构中主要只是“建连协调员”,不是“业务转发通道”。

自定义 transport 接口

如果不想直接使用默认 WebSocket,可以传一个自定义对象,插件会按下面的最小接口调用:

const transport = {
  async connect() {},
  onMessage(handler) {},
  send(payload) {},
  close() {}
}

3. custom 模式

适合:

  • 你已经有自己的信令适配器
  • 你希望复用插件上层的 ConnectCore / PeerLink / DataCore

示例:

import jzWebrtcConnect, { SignalAdapterBase } from '@/uni_modules/jz-webrtc-connect/js_sdk/jz-webrtc-connect'

class MySignalAdapter extends SignalAdapterBase {
  async init() {
    this.peerId = 'custom-peer-id'
    return this.peerId
  }

  connect(remotePeerId) {
    return createYourOwnDataConnection(remotePeerId)
  }
}

await jzWebrtcConnect.configure({
  signal: {
    adapter: 'custom',
    custom: new MySignalAdapter()
  }
})

自定义适配器最少需要实现:

  • init()
  • connect(remotePeerId)
  • onIncoming(handler)
  • onDisconnected(handler)
  • onError(handler)
  • destroy()

事件说明

ConnectCore 常用事件:

事件名 说明
ready 当前节点初始化完成
peer-join 有远端节点接入
peer-leave 有远端节点离开
message 收到普通消息
request 收到 RPC 请求
error 连接或编解码相关错误
state-change 核心状态变化
reconnect-attempt 客户端开始重连
reconnect-success 客户端重连成功
reconnect-fail 客户端重连失败

常见监听方式:

core.on('peer-join', event => {
  console.log(event.peerId, event.role)
})

core.on('peer-leave', event => {
  console.log(event.peerId, event.code, event.reason)
})

core.on('error', event => {
  console.error(event.code, event.message)
})

实际工作流程

native + WebSocket 信令 为例,完整链路通常是:

  1. Host 连接 WebSocket 信令服务,发送 host-ready
  2. Client 连接同一个信令服务并发送 join
  3. 双方通过 WebSocket 交换 offer / answer / candidate
  4. WebRTC 尝试打洞,建立 RTCPeerConnection
  5. DataChannel 打开后,业务消息开始直连传输
  6. 后续高频数据不再依赖信令服务器

这就是这个插件最值得强调的价值点:

  • WebSocket 只承担建连阶段和必要控制面通信
  • 高频业务数据尽量走终端直连
  • 打洞成功后,服务器资源消耗远小于纯 WebSocket 实时转发方案

适合怎么设计业务

推荐把架构拆成两层:

  • 低频控制层:登录、鉴权、房间匹配、信令准备
  • 高频数据层:通过 jz-webrtc-connect 走 WebRTC DataChannel

这种设计相较于“所有实时数据全部走 WebSocket”更适合:

  • 房间内消息频率高
  • 服务端不想承受持续中转压力
  • 对实时性和成本更敏感

常见注意事项

  • 插件只负责通讯能力,不负责业务 UI
  • Host / Client 的连接拓扑是“房主中心化房间模型”,不是全量 mesh
  • broadcast() 仅 Host 可用
  • kick() 仅 Host 可用
  • DataCore 不是必需模块,只做消息收发可不创建
  • 生产环境请认真配置 STUN / TURN,不要只依赖公共 STUN
  • 如果业务极度依赖“完全不走服务器”,需要接受部分网络环境下可能退化到 TURN 的现实

总结

jz-webrtc-connect 的核心价值,不只是“能建 WebRTC 连接”,而是:

  • 用统一 API 屏蔽 PeerJS / native / custom 差异
  • 把高频业务流量从中心服务器转移到终端之间
  • 在打洞成功时实现“业务数据不走服务器”的资源节约效果
  • uni-app 项目可以更清晰地构建“低频信令 + 高频点对点数据”的实时架构

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

暂无用户评论。