OpenHarmony开发者论坛

标题: OpenHarmony_WebSocket连接 [打印本页]

作者: Laval社区小助手    时间: 2024-7-5 14:58
标题: OpenHarmony_WebSocket连接
[md]## 前言

**WebSocket是一种在单个TCP连接上进行全双工通信的协议,于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。WebSocket与Http相比具有更强的实时性和压缩效果、更好的二进制支持、较少的控制开销,并能够保持连接状态。**

## WebSocket介绍

**在OpenHarmony中,WebSocket连接功能主要由@ohos.net.webSocket模块提供。使用该功能需要申请ohos.permission.INTERNET权限。**

### 接口说明

| **接口名**               | **功能描述**                                                                                                                                                |
| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **createWebSocket()**    | **创建一个WebSocket对象,该对象里面包括了建立/关闭连接、发送数据、订阅/取消WebSocket连接的打开事件、接收到服务器消息事件、关闭事件、错误事件 等一系列方法** |
| **connect()**            | **根据URL地址,建立一个WebSocket连接,使用callback和promise方式进行异步回调**                                                                               |
| **send()**               | **通过WebSocket连接发送数据,使用callback和promise方式进行异步回调**                                                                                        |
| **close()**              | **关闭WebSocket连接, 使用callback和promise方式进行异步回调**                                                                                               |
| **on(type: 'open')**     | **订阅WebSocket的打开事件,使用callback方式进行异步回调**                                                                                                   |
| **off(type: 'open')**    | **取消订阅WebSocket的打开事件,使用callback方式进行异步回调**                                                                                               |
| **on(type: 'message')**  | **订阅WebSocket的接收到服务器消息事件,使用callback方式进行异步回调**                                                                                       |
| **off(type: 'message')** | **取消订阅WebSocket的接收到服务器消息事件,使用callback方式进行异步回调**                                                                                   |
| **on(type: 'close')**    | **订阅WebSocket的关闭事件 ,使用callback方式进行异步回调**                                                                                                  |
| **off(type: 'close')**   | **取消订阅WebSocket的关闭事件,使用callback方式进行异步回调**                                                                                               |
| **on(type: 'error')**    | **订阅WebSocket的Error事件,使用callback方式进行异步回调**                                                                                                  |
| **off(type: 'error')**   | **取消订阅WebSocket的Error事件,使用callback方式进行异步回调**                                                                                              |

### 使用场景介绍

**要实现WebSocket建立服务器与客户端的双向连接,需要先通过createWebSocket()方法创建WebSocket对象,然后通过connect()方法连接到服务器。当连接成功后,客户端会收到open事件的回调,之后客户端就可以通过send()方法与服务器进行通信。当服务器发信息给客户端时,客户端会收到message事件的回调。当客户端不要此连接时,可以通过调用close()方法主动断开连接,之后客户端会收到close事件的回调。若在上述任一过程中发生错误,客户端会收到error事件的回调。**

## 开发步骤

* **导入@ohos.net.webSocket模块**
* **创建WebSocket对象**
* **(可选)订阅WebSocket的打开、消息接收、关闭、Error事件**
* **根据URL地址,发起WebSocket连接,与服务器进行通信**
* **使用完WebSocket连接之后,主动断开连接**

## WebSocket连接示例

### 目标

**使用webSocket模块相关接口与服务器进行双向通信**

### 开发环境

**示例开发环境:**

```
IDE: DevEco Studio 3.0 Release(build:3.0.0.993)
SDK: Api Version9
开发模型:Stage
```

### 具体实现

#### 创建工程

**打开DevEco Studio,创建SDK版本为API9、模型为Stage的OpenHarmony项目。工程目录结构如下:**

![](file:///C:/Users/kuangansheng/Desktop/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E5%85%AC%E5%BC%80%E8%AF%BE%E7%A8%8B/OpenHarmony_WebSocket%E8%BF%9E%E6%8E%A5/image/%E5%B7%A5%E7%A8%8B%E7%9B%AE%E5%BD%95.jpg?lastModify=1686119146)

![](https://devpress.csdnimg.cn/d08f0763cbb8474aa5849f5692318ce0.jpg)

#### 配置权限

**在工程中的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) });
   })
  }
}
```

**效果预览如下:**

![](file:///C:/Users/kuangansheng/Desktop/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E5%85%AC%E5%BC%80%E8%AF%BE%E7%A8%8B/OpenHarmony_WebSocket%E8%BF%9E%E6%8E%A5/image/%E7%95%8C%E9%9D%A2%E9%A2%84%E8%A7%88.jpg?lastModify=1686119146)

![](https://devpress.csdnimg.cn/c094a63974304c2a87bc38ecfc6c0b40.jpg)

#### 测试结果

**开发板型号:WAGNER**

**OH版本:3.2.5.5**

**测试服务器url: wss://s2.ripple.com:443**

**发送的数据:**

```
{
"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:

```

## 参考文献

**[1] 应用权限列表. **[https://gitee.com/openharmony/do ... /permission-list.md](https://link.csdn.net/?target=ht ... 3Flogin%3Dfrom_csdn)

**[2] 使用ArkTS语言开发(Stage模型). **[https://gitee.com/openharmony/do ... t-with-ets-stage.md](https://link.csdn.net/?target=ht ... 3Flogin%3Dfrom_csdn)

**[3] WebSocket连接. **[https://gitee.com/openharmony/do ... s-apis-webSocket.md](https://link.csdn.net/?target=ht ... 3Flogin%3Dfrom_csdn)

**[4] WebSocket连接示例. **[https://gitee.com/openharmony/do ... ocket-connection.md](https://link.csdn.net/?target=ht ... 3Flogin%3Dfrom_csdn)

**[5] WebSocket介绍-百度百科. **[https://baike.baidu.com/item/WebSocket/1953845?fr=aladdin](https://link.csdn.net/?target=ht ... 26login%3Dfrom_csdn)
[/md]




欢迎光临 OpenHarmony开发者论坛 (https://forums.openharmony.cn/) Powered by Discuz! X3.5