前言
WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,于 2011 年被 IETF 定为标准 RFC 6455,并由 RFC7936 补充规范。WebSocket API 也被 W3C 定为标准。WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。WebSocket 与 Http 相比具有更强的实时性和压缩效果、更好的二进制支持、较少的控制开销,并能够保持连接状态。
WebSocket 介绍
在 OpenHarmony 中,WebSocket 连接功能主要由 @ohos.net.webSocket 模块提供。使用该功能需要申请 ohos.permission.INTERNET 权限。
接口说明
使用场景介绍
要实现 WebSocket 建立服务器与客户端的双向连接,需要先通过 createWebSocket()方法创建 WebSocket 对象,然后通过 connect()方法连接到服务器。当连接成功后,客户端会收到 open 事件的回调,之后客户端就可以通过 send()方法与服务器进行通信。当服务器发信息给客户端时,客户端会收到 message 事件的回调。当客户端不要此连接时,可以通过调用 close()方法主动断开连接,之后客户端会收到 close 事件的回调。若在上述任一过程中发生错误,客户端会收到 error 事件的回调。
开发步骤
●导入 @ohos.net.webSocket 模块
●创建 WebSocket 对象
●(可选)订阅 WebSocket 的打开、消息接收、关闭、Error 事件
●根据 URL 地址,发起 WebSocket 连接,与服务器进行通信
●使用完 WebSocket 连接之后,主动断开连接
WebSocket 连接示例
目标
使用 webSocket 模块相关接口与服务器进行双向通信
开发环境
示例开发环境:
1.IDE: DevEco Studio 3.0 Release(build:3.0.0.993)
2.SDK: Api Version9
3.开发模型:Stage
具体实现
创建工程
打开 DevEco Studio,创建 SDK 版本为 API9、模型为 Stage 的 OpenHarmony 项目。工程目录结构如下:
配置权限
在工程中的 module.json5 文件中配置 ohos.permission.INTERNET 权限。
"abilities": [
{
...
...
}
],
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
]
包装 WebSocket 接口
在 ets/service 目录下创建 SocketService.ets 文件。为了方便在 UI 页面中调用 WebSocket 相关的功能,在该文件中定义 SocketService 类对 WebSocket 相关接口进行包装。
SocketService.ets:
import webSocket from '@ohos.net.webSocket';
import Logger from '../util/logger'
const TAG = "WebSocketDemo"
export class SocketService {
private socket: webSocket.WebSocket ;
private messageCallback: MessageCallback;
constructor() {
this.createWebSocket();
this.onOpen();
this.onMessage();
this.onClose();
this.onError();
}
/**
* 注册监听器,对服务端发送的消息进行处理
* @param messageListener
*/
public registerMessageListener(messageCallback: MessageCallback) {
this.messageCallback = messageCallback;
}
/**
* 创建WebSocket对象,该对象负责有服务端进行通信
*/
private createWebSocket() {
Logger.info(TAG, "start create websocket");
this.socket = webSocket.createWebSocket();
Logger.info(TAG, "create socket sucess");
}
/**
* 根据指定的url与服务器进行连接
* @param url 协议格式 ws://或wss://
*/
public connect(url: string) {
this.socket.connect(url)
.then((isConnect) => {
if (isConnect) {
Logger.info(TAG, "connect sucess");
}
})
}
/**
* 连接成功后,向服务端发送消息
* @param data
*/
public sendMessage(data: string) {
this.socket.send(data)
.then((isSucess) => {
Logger.info(TAG, "send result:" + isSucess);
if (isSucess) {
Logger.info(TAG, "send message sucess")
}
})
.catch((e) => {
Logger.info(TAG, "send message fail:" + JSON.stringify(e))
})
}
/**
* 主动与服务器断开连接
*/
public closeConnect() {
this.socket.close();
}
/**
* 监听连接打开的事件,当与服务端的连接打开时触发回调
*
*
*/
private onOpen() {
this.socket.on("open", (err, data) => {
Logger.info(TAG, "on open status" + JSON.stringify(data));
})
}
/**
* 监听服务器发送消息的事件,当服务器向客户端发送消息时触发回调
*
*/
private onMessage() {
this.socket.on("message", (err, data) => {
Logger.info(TAG, "receive from server:message is:" + JSON.stringify(data));
this.messageCallback && this.messageCallback(data);
})
}
/**
*
* 监听连接断开事件,当与服务器断开连接时触发回调
*/
private onClose() {
this.socket.on("close", (err, data) => {
Logger.info(TAG, "on close :close code is:" + data.code + ",close reason is:" + data.reason);
})
}
/**
*监听err事件,只要在建立连接、发送数据等任意过程中发生错误,都会触发回调
*
*/
private onError() {
this.socket.on("error", (data) => {
Logger.info(TAG, "on err :err is" + JSON.stringify(data));
})
}
}
interface MessageCallback {
(data: Object): void;
}
let socketService = new SocketService();
export default socketService
创建请求界面
在 ets/pages 目录下创建建 index.ets 文件,使用 Flex、TextInput、Text 等组件构建一个简易的 WebSocket 客户端页面,导入 SocketService 对象进行 WebSocket 通信操作。
index.ets:
import socketService from '../service/SocketService'
import prompt from '@ohos.prompt';
@Entry
@Component
struct Index {
/**
* 请求地址,以ws/wss开头,默认地址为:wss://s2.ripple.com:443
*/
url: string = "wss://s2.ripple.com:443";
/**
* 需要向服务端发送的数据,这里发送一个JSON的字符串
*/
message: string = JSON.stringify({
"id": 1,
"command": "account_info",
"account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59"
});
build() {
Flex({ direction: FlexDirection.Column }) {
Column() {
Row() {
Text("URL:")
.fontSize(25)
.fontColor(Color.Blue)
TextInput()
.fontSize(25)
.fontWeight(FontWeight.Bold)
.onChange((value) => {
this.url = value;
})
}
.margin({ top: 5, bottom: 5 })
Button("开始连接")
.width("60%")
.fontSize(25)
.onClick(() => {
socketService.connect(this.url);
})
}
.border({ width: 1, color: Color.Red })
Column() {
Row() {
Text("DATA:")
.fontSize(25)
.fontColor(Color.Blue)
TextInput()
.fontSize(25)
.fontWeight(FontWeight.Bold)
.onChange((value) => {
this.message = value;
})
}
.margin({ top: 5, bottom: 5 })
Button("发送")
.width("60%")
.fontSize(25)
.onClick(() => {
socketService.sendMessage(this.message);
})
}
.margin({ top: 25 })
.border({ width: 1, color: Color.Green })
Column() {
Button("断开连接")
.width("60%")
.fontSize(25)
.onClick(() => {
socketService.closeConnect();
})
}
.margin({ top: 25 })
}
.width("100%")
.height("100%")
}
/**
* 在声明周期aboutToAppear中注册消息监听器
* @param data
*/
aboutToAppear() {
socketService.registerMessageListener((data) => {
prompt.showDialog({ message: "服务端发来消息:" + JSON.stringify(data) });
})
}
}
效果预览如下:
测试结果
开发板型号:WAGNER
OH 版本:3.2.5.5
测试服务器 url: wss://s2.ripple.com
发送的数据:
{
"id": 1,
"command": "account_info",
"account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59"
}
日志打印:
08-03 17:07:47.421 8160 8160 I 02200/JsApp: WebSocketDemo: start create websocket
08-03 17:07:47.421 8160 8160 I 02200/JsApp: WebSocketDemo: create socket sucess
//连接成功
08-03 17:07:58.176 8160 8160 I 02200/JsApp: WebSocketDemo: connect sucess
08-03 17:07:59.614 8160 8160 I 02200/JsApp: WebSocketDemo: on open status{"status":101,"message":""}
08-03 17:08:03.053 8160 8160 I 02200/JsApp: WebSocketDemo: send result:true
//成功发送消息
08-03 17:08:03.053 8160 8160 I 02200/JsApp: WebSocketDemo: send message sucess
//服务端返回的数据
08-03 17:08:04.124 8160 8160 I 02200/JsApp: WebSocketDemo: receive from server:message is:"{\"id\":1,\"result\":{\"account_data\":{\"Account\":\"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59\",\"Balance\":\"1331561
2686\",\"Flags\":0,\"LedgerEntryType\":\"AccountRoot\",\"OwnerCount\":17,\"PreviousTxnID\":\"02059D06C1A5AFDA5712FD3B9B7F6B48A3B7DA0D6D38D457BEC357BC180910C0\",\"PreviousTxnLgrSeq\":66854742,\"Sequenc
e\":1406,\"index\":\"4F83A2CF7E70F77F79A307E6A472BFC2585B806A70833CCD1C26105BAE0D6E05\"},\"ledger_hash\":\"6FF8D9EE2A3340FB01BC630D52994D9B1B8EA8FCF77014BFFB3E6E086982ADA1\",\"ledger_index\":73440377,
\"validated\":true,\"warnings\":[{\"id\":1004,\"message\":\"This is a reporting server. The default behavior of a reporting server is to only return validated data. If you are looking for not yet val
idated data, include \\\"ledger_index : current\\\" in your request, which will cause this server to forward the request to a p2p node. If the forward is successful the response will include \\\"forwa
rded\\\" : \\\"true\\\"\"}]},\"status\":\"success\",\"type\":\"respon
//连接断开
08-03 17:08:08.016 8160 8160 I 02200/JsApp: WebSocketDemo: on close :close code is:1000,close reason is:
写在最后
有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。
这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。
希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!
获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
鸿蒙(HarmonyOS NEXT)5.0最新学习路线
有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。
获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
《鸿蒙 (OpenHarmony)开发入门教学视频》
《鸿蒙生态应用开发V3.0白皮书》
《鸿蒙 (OpenHarmony)开发基础到实战手册》
OpenHarmony北向、南向开发环境搭建
《鸿蒙开发基础》
●ArkTS语言
●安装DevEco Studio
●运用你的第一个ArkTS应用
●ArkUI声明式UI开发
.……
《鸿蒙开发进阶》
●Stage模型入门
●网络管理
●数据管理
●电话服务
●分布式应用开发
●通知与窗口管理
●多媒体技术
●安全技能
●任务管理
●WebGL
●国际化开发
●应用测试
●DFX面向未来设计
●鸿蒙系统移植和裁剪定制
……
《鸿蒙进阶实战》
●ArkTS实践
●UIAbility应用
●网络案例
……