更新记录

1.0.0(2026-02-06)

  • 首次发布。
  • 支持 TCP 客户端:连接、发送、接收、关闭。
  • 支持 UDP:绑定、发送、接收、broadcast 开关。
  • 支持字符串与 ArrayBuffer 两种数据类型。
  • 提供统一错误码、日志控制与基础编解码工具。

平台兼容性

uni-app(4.87)

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

uni-app x(4.87)

Chrome Safari Android iOS 鸿蒙 微信小程序
- - - -

hans-socket

App 端 UTS Socket 插件,提供 TCP 客户端与 UDP 通信能力,适用于设备通信、局域网发现、网关控制等场景。

本 README 的示例来自仓库内两个页面(API 一致):

  • uniappx-socket-playground/pages/socket/socket.uvue(uni-app x)
  • uniapp-socket-playground/pages/socket/socket.vue(uni-app)

下载与安装

  1. 打开 HBuilderX → 插件市场 → 搜索 hans-socket
  2. 点击“导入插件”,插件会进入项目 uni_modules/hans-socket
  3. 在页面 script 中引入 API。

平台支持

平台 TCP UDP 说明
Android 支持 broadcast;可选 androidMulticastLock
iOS 支持 broadcast(受系统/网络环境限制)
Harmony - - 调用返回 9020101 NOT_SUPPORTED

框架支持(uni-app / uni-app x)请以当前插件 package.jsonuni_modules.platforms 为准。

推荐使用流程

  1. createTcpSocket / createUdpSocket 创建实例(拿到 socketId)。
  2. 立刻注册 onOpen/onMessage/onClose/onError(或 UDP 对应事件)。
  3. TCP 走 tcpConnect,UDP 走 udpBind(按需 udpSetBroadcast)。
  4. 收发数据(文本 / ArrayBuffer / bytesMessage)。
  5. 页面离开时调用 tcpClose / udpClose 回收资源。

快速开始(uni-app x)

<script setup lang="uts">
import {
  createTcpSocket,
  tcpConnect,
  tcpSendText,
  tcpOnOpen,
  tcpOnMessage,
  tcpOnError,
  tcpOnClose,
  tcpClose,
  createUdpSocket,
  udpBind,
  udpSetBroadcast,
  udpSendTextTo,
  udpOnListening,
  udpOnMessage,
  udpOnError,
  udpOnClose,
  udpClose
} from '@/uni_modules/hans-socket'

let tcpId: number = 0
let udpId: number = 0

function startTcp() {
  tcpId = createTcpSocket({ receiveType: 'string', encoding: 'utf-8' })
  tcpOnOpen(tcpId, () => tcpSendText(tcpId, 'hello'))
  tcpOnMessage(tcpId, (res) => console.log('tcp.message', res.data ?? res.buffer))
  tcpOnError(tcpId, (err) => console.error('tcp.error', err.errCode, err.errMsg))
  tcpOnClose(tcpId, (res) => { console.log('tcp.close', res.hadError); tcpId = 0 })
  tcpConnect(tcpId, '127.0.0.1', 9000, 15000)
}

function startUdp() {
  udpId = createUdpSocket({ receiveType: 'string', encoding: 'utf-8', enableBroadcast: true })
  udpOnListening(udpId, () => console.log('udp.listening'))
  udpOnMessage(udpId, (res) => console.log('udp.message', res.address, res.port, res.data ?? res.buffer))
  udpOnError(udpId, (err) => console.error('udp.error', err.errCode, err.errMsg))
  udpOnClose(udpId, () => { udpId = 0 })
  udpSetBroadcast(udpId, true)
  udpBind(udpId, { port: 7779, address: '0.0.0.0', reuseAddress: true, androidMulticastLock: false })
  udpSendTextTo(udpId, '127.0.0.1', 7777, 'ping')
}

function destroyAll() {
  if (tcpId != 0) tcpClose(tcpId)
  if (udpId != 0) udpClose(udpId)
}
</script>

快速开始(uni-app)

<script setup>
import { ref } from 'vue'
import { onUnload } from '@dcloudio/uni-app'
import {
  createTcpSocket,
  tcpConnect,
  tcpSendText,
  tcpOnOpen,
  tcpOnMessage,
  tcpOnError,
  tcpClose,
  createUdpSocket,
  udpBind,
  udpSendTextTo,
  udpOnMessage,
  udpSetBroadcast,
  udpClose
} from '@/uni_modules/hans-socket'

const tcpId = ref(0)
const udpId = ref(0)

function startTcp() {
  if (tcpId.value !== 0) return
  tcpId.value = createTcpSocket({ receiveType: 'string', encoding: 'utf-8' })
  tcpOnOpen(tcpId.value, () => tcpSendText(tcpId.value, 'hello'))
  tcpOnMessage(tcpId.value, (res) => console.log('tcp.message', res.data ?? res.buffer))
  tcpOnError(tcpId.value, (err) => console.error('tcp.error', err.errCode, err.errMsg))
  tcpConnect(tcpId.value, '127.0.0.1', 9000, 15000)
}

function startUdp() {
  if (udpId.value !== 0) return
  udpId.value = createUdpSocket({ receiveType: 'string', encoding: 'utf-8', enableBroadcast: true })
  udpSetBroadcast(udpId.value, true)
  udpBind(udpId.value, { port: 7779, address: '0.0.0.0', reuseAddress: true })
  udpOnMessage(udpId.value, (res) => console.log('udp.message', res.address, res.port, res.data ?? res.buffer))
  udpSendTextTo(udpId.value, '127.0.0.1', 7777, 'ping')
}

onUnload(() => {
  if (tcpId.value !== 0) tcpClose(tcpId.value)
  if (udpId.value !== 0) udpClose(udpId.value)
})
</script>

进阶用法(来自 playground 实战)

1) bytesMessage 发包

bytesMessage 是 JSON 字符串,内容为字节数组(数字或十六进制字符串):

// 数字数组
tcpSendBytesMessage(tcpId, '[1,2,3,4]')

// 16 进制字符串数组
const payload = JSON.stringify(['53', '53', '01', 'c0', '00', 'A9'])
udpSendBytesMessageTo(udpId, '127.0.0.1', 7777, payload)

2) 指定本地端口发送 UDP

udpSendTextToFromPort(udpId, '192.168.1.100', 7777, 9527, 'hello')
udpSendBytesMessageToFromPort(udpId, '192.168.1.100', 7777, 9527, '[0,1,2,3]')

3) 先发送再绑定(同一 UDP socket)

playground 已验证 send-only -> bind -> receive 流程,可用于某些“先探测后监听”场景。

4) 二进制调试

const hex = arrayBufferToHex(buffer, false)
const ab = bytesMessageToArrayBuffer('[9,8,7,6]')

API 一览

TCP

  • createTcpSocket(options?)
  • tcpConnect(id, host, port, timeoutMs?)
  • tcpSendText(id, data) / tcpSendBuffer(id, buffer) / tcpSendBytesMessage(id, bytesMessage)
  • tcpClose(id)
  • tcpOnOpen(id, callback)
  • tcpOnMessage(id, callback)
  • tcpOnClose(id, callback)
  • tcpOnError(id, callback)
  • tcpGetState(id)

UDP

  • createUdpSocket(options?)
  • udpBind(id, options)
  • udpSendTextTo(id, address, port, data)
  • udpSendBufferTo(id, address, port, buffer)
  • udpSendBytesMessageTo(id, address, port, bytesMessage)
  • udpSendTextToFromPort(id, address, port, localPort, data)
  • udpSendBufferToFromPort(id, address, port, localPort, buffer)
  • udpSendBytesMessageToFromPort(id, address, port, localPort, bytesMessage)
  • udpSetBroadcast(id, enabled)
  • udpClose(id)
  • udpOnListening(id, callback)
  • udpOnMessage(id, callback)
  • udpOnClose(id, callback)
  • udpOnError(id, callback)

工具函数

  • setLogEnabled(enabled) / isLogEnabled()
  • arrayBufferToHex(buffer, uppercase?)
  • hexToArrayBuffer(hex)
  • bytesMessageToArrayBuffer(bytesMessage)

关键参数说明

  • receiveType: 'string' | 'arraybuffer',默认 'string'
  • encoding: 默认 utf-8。playground 示例包含 utf-8 / ascii / iso-8859-1 / gbk / gb18030
  • UdpBindOptions.port: 监听端口,取值范围 1 ~ 65535
  • UdpBindOptions.address: 监听地址,常用 0.0.0.0
  • UdpBindOptions.reuseAddress: 端口复用(不同系统语义可能有差异)。
  • UdpBindOptions.androidMulticastLock: Android 下优化 broadcast/multicast 收包。

权限说明

Android

  • 必需:INTERNET
  • 可选(broadcast/multicast 场景):CHANGE_WIFI_MULTICAST_STATEACCESS_WIFI_STATE

iOS

  • iOS 14+ 局域网访问需要 Local Network 授权(NSLocalNetworkUsageDescription

使用注意

  • 同一 socket 的同一事件(tcpOn* / udpOn*)重复注册会覆盖上一次回调。
  • receiveType='string' 时读取 res.datareceiveType='arraybuffer' 时读取 res.buffer
  • TCP 是字节流,message 回调不等于业务消息边界,请自行做拆包/粘包。
  • Android 模拟器访问宿主机建议使用 10.0.2.2(playground 已按此处理默认值)。
  • 页面销毁/退出时务必调用 tcpClose / udpClose

错误码

  • 9020101 NOT_SUPPORTED
  • 9020102 INVALID_ARGUMENT
  • 9020103 INVALID_STATE
  • 9020104 UNSUPPORTED_ENCODING
  • 9020201 TCP_CONNECT_FAILED
  • 9020202 TCP_SEND_FAILED
  • 9020203 TCP_RECEIVE_FAILED
  • 9020204 TCP_TIMEOUT
  • 9020301 UDP_CREATE_FAILED
  • 9020302 UDP_BIND_FAILED
  • 9020303 UDP_SEND_FAILED
  • 9020304 UDP_RECEIVE_FAILED
  • 9020999 UNKNOWN

隐私、权限声明

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

Android: INTERNET(必需), CHANGE_WIFI_MULTICAST_STATE/ACCESS_WIFI_STATE(可选,broadcast/multicast 场景); iOS: NSLocalNetworkUsageDescription(局域网访问场景)

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

插件本身不采集、不上传用户个人数据;网络数据仅按业务调用进行传输。

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

暂无用户评论。