更新记录

1.0.0(2026-10-31)

初始版本:WebSocket / TCP / UDP 多会话(Android / iOS / 鸿蒙)

  • 事件:onOpen / onMessage / onClose / onError;文本 utf8 + 二进制 base64
  • Android:OkHttp + Socket + DatagramSocket;iOS:URLSessionWebSocket + NWConnection;鸿蒙:@kit.NetworkKit(含 ohos.permission.INTERNET)
  • JS 托管 createManagedSocket:帧协议(length2 / length4 / delimiter)、心跳、空闲超时、自动重连、状态机、发送队列
  • TCP 原生收包统一 base64;组件 <zv-socket>

平台兼容性

uni-app(4.41)

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

zv-socket

原生 Socket:WebSocket + TCP + UDP(Android / iOS / 鸿蒙)+ JS 托管层(帧协议 / 心跳 / 重连 / 发送队列)。

本人设备有限,没有做全部测试,请先试用,确认正常后再购买

类型 Android iOS 鸿蒙 说明
ws ✅ OkHttp ✅ URLSessionWebSocket ✅ @kit.NetworkKit webSocket 文本为主;二进制用 base64
tcp ✅ java.net.Socket ✅ NWConnection ✅ socket.TCPSocket 收包 base64 字节流;托管层可拆帧
udp ✅ DatagramSocket ✅ NWConnection(UDP) ✅ socket.UDPSocket 每包独立

H5 为桩(9030001)。App 需 自定义调试基座 / 云打包。

推荐:托管会话 createManagedSocket

import { createManagedSocket } from '@/uni_modules/zv-socket/js_sdk'

const sock = createManagedSocket({
  type: 'tcp',
  host: '192.168.1.10',
  port: 9000,
  // 帧:none | length2 | length4 | delimiter
  frameMode: 'length4',
  delimiter: '\n',
  heartbeatInterval: 15000,
  heartbeatPayload: 'ping',
  idleTimeout: 45000,
  autoReconnect: true,
  reconnectDelay: 1000,
  reconnectMaxDelay: 30000,
  maxRetry: 10,          // -1 无限
  maxQueue: 200,
  onState: (s) => console.log(s), // connecting|connected|reconnecting|closed
  onOpen: (e) => {},
  onMessage: (e) => console.log(e.data, e.framed),
  onClose: (e) => console.log(e.active),
  onError: (e) => {},
  onReconnect: ({ attempt, delay }) => {}
})

sock.connect()
sock.send('hello')   // 未连上先入队,连上后冲刷
sock.close()         // 主动关闭,不再重连

参数说明

字段 类型 默认 含义
type 'tcp' \| 'udp' \| 'ws' 'tcp' 协议类型。UDP 不会自动重连、不启用心跳/空闲超时。
host string '' TCP/UDP 对端 IP 或域名(type 为 tcp/udp 时必填)。
port number 0 TCP/UDP 对端端口。
url string '' WebSocket 完整地址,如 ws://host:8080/path(type:'ws' 时用这个,不用 host/port)。
localPort number 不传 仅 UDP:本机绑定端口;0 或不传表示系统分配。
timeout number 10000 连接超时(毫秒)。超时走失败/关闭逻辑,可触发重连。

帧协议(主要对 TCP;粘包/拆包)

字段 类型 默认 含义
frameMode 'none' \| 'length2' \| 'length4' \| 'delimiter' 'none' 收发如何组帧。仅 TCP 生效;ws/udp 按消息/数据报原样回调。
delimiter string '\n' 仅 frameMode:'delimiter':帧结束分隔符(UTF-8)。发送时自动追加,接收按分隔符切开。
maxFrameSize number 1048576(1MB) 单帧最大字节;缓冲超限会报错(9030004)。

frameMode 取值:

  • none:不拆帧。TCP 底层收包是 base64 字节流,托管层会尽量解成 utf8 文本块 再 onMessage;发送也不加长度头。适合「对方发的就是文本块」或你自己在业务里拼。
  • length2:每帧前 2 字节 大端 无符号长度(payload 最长 65535),再跟正文。收发都会按此封/拆。
  • length4:每帧前 4 字节 大端 无符号长度 + 正文。适合二进制/变长协议。
  • delimiter:按 delimiter 切帧(如一行一条 \n)。发送时自动在末尾补分隔符。

示例里写 frameMode:'length4' 同时又写 delimiter:只有改成 'delimiter' 时 delimiter 才有用;length4 下可省略 delimiter。

心跳 / 空闲

字段 类型 默认 含义
heartbeatInterval number 0(关闭) 已连接后每隔多少 毫秒 自动 send(heartbeatPayload)。≤0 不心跳。UDP 忽略。
heartbeatPayload string 'ping' 心跳内容。会走与业务相同的封帧规则(TCP + 非 none 时也会封帧)。
idleTimeout number 0(关闭) 距上次 收到 数据超过该毫秒数则主动断开(错误码偏 9030006),若开启自动重连会再连。≤0 不检测。UDP 忽略。

说明:心跳只负责「定时往外发」;是否判定对方活着,通常靠 idleTimeout(对方有回包才会刷新空闲计时)。

自动重连 / 发送队列

字段 类型 默认 含义
autoReconnect boolean true(UDP 强制不重连) 意外断开(对端关、超时、网络失败等)是否自动重连。调用 close() / destroy() 为主动关闭,一律不重连。
reconnectDelay number 1000 首次重连等待毫秒;之后指数退避:min(reconnectMaxDelay, reconnectDelay * 2^attempt)。
reconnectMaxDelay number 30000 单次重连等待上限(毫秒),避免退避无限变大。
maxRetry number -1 最多重连次数。-1 无限;10 表示最多再试 10 次,用尽后 closed 并 onError(含 maxRetry reached)。
maxQueue number 200 未连接时 send 入队上限;超了 丢掉最旧 再入队。连上后在 onOpen 里按序冲刷。

回调

字段 签名 含义
onState (state, sock) => void 状态变化:connecting 首次连 / connected 已通 / reconnecting 退避等待或重连中 / closed 结束。
onOpen (e) => void 底层连接成功(含重连成功)。此时会启心跳、刷发送队列。
onMessage (e) => void 收到业务数据。e.data 为内容;e.framed === true 表示经帧解析拆出;e.encoding 多为 utf8/base64;TCP 拆帧时还有 e.raw。
onClose (e) => void 关闭。e.active === true 表示你调了 close();false 表示对端/网络断开(之后可能重连)。
onError (e) => void 错误:e.errCode / e.errMsg(含连接失败、发送失败、拆帧失败、重连次数用尽等)。
onReconnect ({ attempt, delay, maxRetry }) => void 即将重连前触发。attempt 从 1 起;delay 为本次等待毫秒。

实例方法

方法 说明
connect() 开始连接;已在 connecting/connected 时直接返回。
send(data, sendOpts?) 发数据。未连接则入队,返回 { queued:true, queueSize };已连接返回 { queued:false }。sendOpts.skipFrame:true 可跳过 TCP 封帧;UDP 可传 { host, port } 指定对端。
close(reason?) 主动关闭:清定时器、清空队列、不再重连。
destroy() 同 close('destroy')。
getState() / isConnected() 读当前状态 / 是否 connected。

组件:<zv-socket>(easycom),slot 暴露 state / connected / lastMessage 等,方法 connect / send / close。

底层 API(原始)

import {
  createSocket, sendSocket, closeSocket,
  onSocket, offSocket, closeAllSockets
} from '@/uni_modules/zv-socket'

onSocket({
  onOpen: (e) => {},
  onMessage: (e) => console.log(e.encoding, e.data), // TCP 为 base64
  onClose: (e) => {},
  onError: (e) => {}
})

createSocket({ type: 'tcp', host: '192.168.1.10', port: 9000 })
createSocket({ type: 'udp', host: '…', port: 9001, localPort: 0 })
createSocket({ type: 'ws', url: 'ws://192.168.1.10:8080/path' })

sendSocket({ socketId, data: 'hello', encoding: 'utf8' })
sendSocket({ socketId, data: uni.arrayBufferToBase64(buf), encoding: 'base64' })

readyState(底层)

0 连接中 · 1 已连接/已绑定 · 2 关闭中 · 3 已关闭

错误码

9030001 平台不支持 · 9030002 参数错误 · 9030003 连接失败 · 9030004 发送失败 · 9030005 会话不存在 · 9030006 已关闭/空闲超时

注意

  • TCP 收包为 encoding:'base64'(保字节流);文本业务请用 createManagedSocket(frameMode:'none' 会解成 utf8)。
  • 鸿蒙需 ohos.permission.INTERNET(插件已声明)。
  • UDP onMessage 带 remoteHost / remotePort。
  • iOS 明文 ws:// / TCP 可能需 ATS 例外。
  • 页面销毁请 close() / closeAllSockets()。

与 Android 行为对照(鸿蒙)

项 对齐情况
API / 错误码 / 会话生命周期 ✅ 同 interface.uts
TCP 收包 base64、发送 utf8/base64 ✅
UDP utf8 + remoteHost/Port;未 bind 先发自动 bind ✅
WS 文本 utf8;连接超时 timeout ✅(鸿蒙用定时器补齐)
TCP TCPNoDelay、域名/IPv6 地址 ✅(域名需 API 18+ family=3)
WS 二进制帧 Android / 鸿蒙 ✅ 收包 encoding:'base64'
回调线程 Android 强制主线程;鸿蒙为 NetworkKit 异步回调(一般可直接更新 UI)
明文 ws:// 两端均可;生产建议 wss://

隐私、权限声明

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

Android: - android.permission.INTERNET(建立 WebSocket / TCP / UDP 网络连接) - android.permission.ACCESS_NETWORK_STATE(查询网络状态,辅助连接) 鸿蒙 HarmonyOS: - ohos.permission.INTERNET(同上,建立网络连接收发数据) iOS: - 无额外隐私权限清单项;若业务使用明文 ws:// 或非 HTTPS,可能需在应用侧配置 ATS 例外(由宿主 App 配置,非插件单独弹权)

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

插件不采集任何数据

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

无

暂无用户评论。