• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 使用WebSocket访问网络
2<!--Kit: Network Kit-->
3<!--Subsystem: Communication-->
4<!--Owner: @wmyao_mm-->
5<!--Designer: @guo-min_net-->
6<!--Tester: @tongxilin-->
7<!--Adviser: @zhang_yixin13-->
8
9## 场景介绍
10
11WebSocket是一种网络通信协议,它允许客户端和服务器之间建立一个持久的连接,并在该连接上进行全双工通信,连接之后客户端和服务器端可以同时主动发送数据,这是WebSocket和传统的HTTP协议最大的区别,HTTP以单向通信为主,客户端发起请求,服务器端响应数据,一次传输之后,连接会断开。一般情况下,HTTP适用于一次性数据获取(如网页内容加载),Websocket适用于实时性要求高的场景下(如在线聊天、实时游戏),以避免频繁建立连接提升用户体验。
12
13该模块给第三方应用提供webSocket客户端和服务端能力,实现客户端与服务端的双向连接,目前服务端仅支持智慧屏使用。
14
15客户端:使用WebSocket建立服务器与客户端的双向连接,需要先通过[createWebSocket()](../reference/apis-network-kit/js-apis-webSocket.md#websocketcreatewebsocket6)方法创建[WebSocket](../reference/apis-network-kit/js-apis-webSocket.md#websocket6)对象,然后通过[connect()](../reference/apis-network-kit/js-apis-webSocket.md#connect6)方法连接到服务器。当连接成功后,客户端会收到[open](../reference/apis-network-kit/js-apis-webSocket.md#onopen6)事件的回调,之后客户端就可以通过[send()](../reference/apis-network-kit/js-apis-webSocket.md#send6)方法与服务器进行通信。当服务器发信息给客户端时,客户端会收到[message](../reference/apis-network-kit/js-apis-webSocket.md#onmessage6)事件的回调。当客户端想要取消此连接时,通过调用[close()](../reference/apis-network-kit/js-apis-webSocket.md#close6)方法主动断开连接后,客户端会收到[close](../reference/apis-network-kit/js-apis-webSocket.md#onclose6)事件的回调。若在上述任一过程中发生错误,客户端会收到[error](../reference/apis-network-kit/js-apis-webSocket.md#onerror6)事件的回调。
16
17服务端:(目前服务端仅支持智慧屏使用)使用WebSocket建立服务器与客户端的双向连接,需要先通过[createWebSocketServer()](../reference/apis-network-kit/js-apis-webSocket.md#websocketcreatewebsocketserver19)方法创建[WebSocketServer](../reference/apis-network-kit/js-apis-webSocket.md#websocketserver19)对象,然后通过[start()](../reference/apis-network-kit/js-apis-webSocket.md#start19)方法启动服务器,监听客户端申请建链的消息。当连接成功后,服务端会收到[connect](../reference/apis-network-kit/js-apis-webSocket.md#onconnect19)事件的回调,之后服务端可以通过[send()](../reference/apis-network-kit/js-apis-webSocket.md#send19)方法与客户端进行通信,可以通过[listAllConnections()](../reference/apis-network-kit/js-apis-webSocket.md#listallconnections19)方法列举出当前与服务端建链的所有客户端信息。当客户端给服务端发消息时,服务端会收到[messageReceive](../reference/apis-network-kit/js-apis-webSocket.md#onmessagereceive19)事件回调。当服务端想断开某个与客户端的连接时,可以通过调用[close()](../reference/apis-network-kit/js-apis-webSocket.md#close19)方法主动断开与某个客户端的连接,之后服务端会收到[close](../reference/apis-network-kit/js-apis-webSocket.md#onclose19)事件的回调。当服务端想停止service时,可以调用[stop()](../reference/apis-network-kit/js-apis-webSocket.md#stop19)方法。若在上述任一过程中发生错误,服务端会收到[error](../reference/apis-network-kit/js-apis-webSocket.md#onerror19)事件的回调。
18
19> **说明:**
20>
21> websocket支持[心跳检测机制](https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.2),在客户端和服务端建立webSocket连接之后,从连接建立或者客户端收到Pong帧开始计时,每间隔pingInterval秒客户端会发送Ping帧给服务器。服务器若支持websocket协议则会在收到Ping帧后自动回复Pong帧,表示连接正常,若服务端异常或服务端不支持websocket协议则不会回复Pong帧;若Ping帧发出去后,pongTimeout秒内没有收到Pong帧,则会主动断开连接。支持开发者关闭心跳检测机制,自定义pingInterval与pongTimeout,详情请参考[WebsocketRequestOptions](../reference/apis-network-kit/js-apis-webSocket.md#websocketrequestoptions)。
22
23## client端开发步骤
24
251. 导入webSocket以及错误码模块。
26
27    ```js
28    import { webSocket } from '@kit.NetworkKit';
29    import { BusinessError } from '@kit.BasicServicesKit';
30    ```
31
322. 创建WebSocket连接,返回一个WebSocket对象。
33
34    ```js
35    let defaultIpAddress = "ws://";
36    let ws = webSocket.createWebSocket();
37    ```
38
393. 订阅WebSocket的打开、消息接收、关闭、Error事件(可选),当收到on('open')事件时,可以通过send()方法与服务器进行通信,当收到服务器的`bye`消息时(此消息字段仅为示意,具体字段需要与服务器协商),主动断开连接。。
40
41    ```js
42    ws.on('open', (err: BusinessError, value: Object) => {
43      console.log("on open, status:" + JSON.stringify(value));
44      // 当收到on('open')事件时,可以通过send()方法与服务器进行通信。
45      ws.send("Hello, server!", (err: BusinessError, value: boolean) => {
46        if (!err) {
47          console.log("Message send successfully");
48        } else {
49          console.error("Failed to send the message. Err:" + JSON.stringify(err));
50        }
51      });
52    });
53    ws.on('message', (err: BusinessError, value: string | ArrayBuffer) => {
54      console.log("on message, message:" + value);
55      // 当收到服务器的`bye`消息时(此消息字段仅为示意,具体字段需要与服务器协商),主动断开连接。
56      if (value === 'bye') {
57        ws.close((err: BusinessError, value: boolean) => {
58          if (!err) {
59            console.log("Connection closed successfully");
60          } else {
61            console.error("Failed to close the connection. Err: " + JSON.stringify(err));
62          }
63        });
64      }
65    });
66    ws.on('close', (err: BusinessError, value: webSocket.CloseResult) => {
67      console.log("on close, code is " + value.code + ", reason is " + value.reason);
68    });
69    ws.on('error', (err: BusinessError) => {
70      console.error("on error, error:" + JSON.stringify(err));
71    });
72    ```
73
744. 根据URL地址,发起WebSocket连接。
75
76    ```js
77    ws.connect(defaultIpAddress, (err: BusinessError, value: boolean) => {
78      if (!err) {
79        console.log("Connected successfully");
80      } else {
81        console.error("Connection failed. Err:" + JSON.stringify(err));
82      }
83    });
84    ```
85
86## server端开发步骤
87
881. 导入webSocket以及错误码模块。
89
90    ```js
91    import { webSocket } from '@kit.NetworkKit';
92    import { BusinessError } from '@kit.BasicServicesKit';
93    ```
94
952. 创建WebSocketServer对象。
96
97    ```js
98    let localServer: webSocket.WebSocketServer;
99    localServer = webSocket.createWebSocketServer();
100    ```
101
1023. 订阅WebSocketServer的客户端连接事件、消息接收事件、关闭事件、Error事件(可选),在收到客户端连接事件后,服务端可以通过send()方法与客户端进行通信,当收到客户端的"bye"消息时(此消息字段仅为示意,具体字段需要与客户端协商),主动断开连接。
103
104    ```js
105    localServer.on('connect', async (connection: webSocket.WebSocketConnection) => {
106      console.info(`New client connected! Client ip: ${connection.clientIP}, Client port: ${connection.clientPort}`);
107      // 当收到on('connect')事件时,可以通过send()方法与客户端进行通信。
108      localServer.send("Hello, I'm server!", connection).then((success: boolean) => {
109        if (success) {
110          console.info('message send successfully');
111        } else {
112          console.error('message send failed');
113        }
114      }).catch((error: BusinessError) => {
115          console.error(`message send failed, Code: ${error.code}, message: ${error.message}`);
116      });
117    });
118
119    localServer.on('messageReceive', (message: webSocket.WebSocketMessage) => {
120      try{
121        console.info(`on message received, client: ${message.clientConnection}, data: ${message.data}`);
122        // 当收到客户端的"bye"消息时(此消息字段仅为示意,具体字段需要与客户端协商),主动断开连接。
123        if (message.data === 'bye') {
124          localServer.close(message.clientConnection).then((success: boolean) => {
125            if (success) {
126              console.info('close client successfully');
127            } else {
128              console.error('close client failed');
129            }
130          });
131        }
132      } catch (error) {
133        console.error(`on messageReceive failed. Code: ${error.code}, message: ${error.message}`);
134      }
135    });
136
137    localServer.on('close', (clientConnection: webSocket.WebSocketConnection, closeReason: webSocket.CloseResult) => {
138      console.info(`client close, client: ${clientConnection}, closeReason: Code: ${closeReason.code}, reason: ${closeReason.reason}`);
139    });
140
141    localServer.on('error', (error: BusinessError) => {
142      console.error(`error. Code: ${error.code}, message: ${error.message}`);
143    });
144    ```
145
1464. 配置config参数启动server端服务。
147
148    ```js
149    let config: webSocket.WebSocketServerConfig = {
150      // 监听端口。
151      serverPort: 8080,
152      maxConcurrentClientsNumber: 10,
153      maxConnectionsForOneClient: 10,
154    }
155    localServer.start(config).then((success: boolean) => {
156      if (success) {
157        console.info('webSocket server start success');
158      } else {
159        console.error('websocket server start failed');
160      }
161    }).catch((error: BusinessError) => {
162      console.error(`Failed to start. Code: ${error.code}, message: ${error.message}`);
163    });
164    ```
165
1665. 服务端监听所有客户端连接状态(可选)。
167
168    ```js
169    let connections: webSocket.WebSocketConnection[] = [];
170    try {
171      connections = await localServer.listAllConnections();
172      if (connections.length === 0) {
173        console.info('client list is empty');
174      } else {
175        console.error(`client list cnt: ${connections.length}, client connections list is: ${connections}`);
176      }
177    } catch (error) {
178      console.error(`Failed to listAllConnections. Code: ${error.code}, message: ${error.message}`);
179    }
180    ```
181
1826. 需要关闭WebSocketServer端服务器时,可以通过stop()停止服务。
183
184    ```js
185    localServer.stop().then((success: boolean) => {
186      if (success) {
187        console.info('server stop service successfully');
188      } else {
189        console.error('server stop service failed');
190      }
191    });
192    ```
193
194## 客户端完整示例
195
196**示例:**
197
198```js
199import { webSocket } from '@kit.NetworkKit';
200import { BusinessError } from '@kit.BasicServicesKit';
201
202let defaultIpAddress = "ws://";
203let ws = webSocket.createWebSocket();
204ws.on('open', (err: BusinessError, value: Object) => {
205  console.log("on open, status:" + JSON.stringify(value));
206  // 当收到on('open')事件时,可以通过send()方法与服务器进行通信。
207  ws.send("Hello, server!", (err: BusinessError, value: boolean) => {
208    if (!err) {
209      console.log("Message send successfully");
210    } else {
211      console.error("Failed to send the message. Err:" + JSON.stringify(err));
212    }
213  });
214});
215ws.on('message', (err: BusinessError, value: string | ArrayBuffer) => {
216  console.log("on message, message:" + value);
217  // 当收到服务器的`bye`消息时(此消息字段仅为示意,具体字段需要与服务器协商),主动断开连接。
218  if (value === 'bye') {
219    ws.close((err: BusinessError, value: boolean) => {
220      if (!err) {
221        console.log("Connection closed successfully");
222      } else {
223        console.error("Failed to close the connection. Err: " + JSON.stringify(err));
224      }
225    });
226  }
227});
228ws.on('close', (err: BusinessError, value: webSocket.CloseResult) => {
229  console.log("on close, code is " + value.code + ", reason is " + value.reason);
230});
231ws.on('error', (err: BusinessError) => {
232  console.error("on error, error:" + JSON.stringify(err));
233});
234ws.connect(defaultIpAddress, (err: BusinessError, value: boolean) => {
235  if (!err) {
236    console.log("Connected successfully");
237  } else {
238    console.error("Connection failed. Err:" + JSON.stringify(err));
239  }
240});
241```
242
243## server端完整示例
244
2451. 导入需要的webSocket模块。
246
2472. 创建一个WebSocketServer对象。
248
2493. (可选)订阅WebSocketServer的客户端连接事件、消息接收事件、关闭事件、Error事件。
250
2514. 配置config参数,通过start()启动server端服务。
252
2535. 通过WebSocketServer收发消息、监听事件等。
254
2556. 使用完WebSocketServer端服务器后,通过stop()停止服务。
256
257**示例:**
258
259```js
260import { webSocket } from '@kit.NetworkKit';
261import { BusinessError } from '@kit.BasicServicesKit';
262
263let connections: webSocket.WebSocketConnection[] = [];
264let localServer: webSocket.WebSocketServer;
265let config: webSocket.WebSocketServerConfig = {
266  // 监听端口。
267  serverPort: 8080,
268  maxConcurrentClientsNumber: 10,
269  maxConnectionsForOneClient: 10,
270}
271
272localServer = webSocket.createWebSocketServer();
273
274localServer.on('connect', async (connection: webSocket.WebSocketConnection) => {
275  console.info(`New client connected! Client ip: ${connection.clientIP}, Client port: ${connection.clientPort}`);
276  // 当收到on('connect')事件时,可以通过send()方法与客户端进行通信。
277  localServer.send("Hello, I'm server!", connection).then((success: boolean) => {
278    if (success) {
279      console.info('message send successfully');
280    } else {
281      console.error('message send failed');
282    }
283  }).catch((error: BusinessError) => {
284    console.error(`message send failed, Code: ${error.code}, message: ${error.message}`);
285  });
286
287  try {
288    connections = await localServer.listAllConnections();
289    if (connections.length === 0) {
290      console.info('client list is empty');
291    } else {
292      console.info(`client list cnt: ${connections.length}, client connections list is: ${connections}`);
293    }
294  } catch (error) {
295    console.error(`Failed to listAllConnections. Code: ${error.code}, message: ${error.message}`);
296  }
297});
298
299localServer.on('messageReceive', (message: webSocket.WebSocketMessage) => {
300  try{
301    console.info(`on message received, client: ${message.clientConnection}, data: ${message.data}`);
302    // 当收到客户端的"bye"消息时(此消息字段仅为示意,具体字段需要与客户端协商),主动断开连接。
303    if (message.data === 'bye') {
304      localServer.close(message.clientConnection).then((success: boolean) => {
305        if (success) {
306          console.info('close client successfully');
307        } else {
308          console.error('close client failed');
309        }
310      });
311    }
312  } catch (error) {
313    console.error(`on messageReceive failed. Code: ${error.code}, message: ${error.message}`);
314  }
315});
316
317localServer.on('close', (clientConnection: webSocket.WebSocketConnection, closeReason: webSocket.CloseResult) => {
318  console.info(`client close, client: ${clientConnection}, closeReason: Code: ${closeReason.code}, reason: ${closeReason.reason}`);
319});
320
321localServer.on('error', (error: BusinessError) => {
322  console.error(`error. Code: ${error.code}, message: ${error.message}`);
323});
324
325localServer.start(config).then((success: boolean) => {
326  if (success) {
327    console.info('webSocket server start success');
328  } else {
329    console.error('websocket server start failed');
330  }
331}).catch((error: BusinessError) => {
332  console.error(`Failed to start. Code: ${error.code}, message: ${error.message}`);
333});
334
335localServer.stop().then((success: boolean) => {
336  if (success) {
337    console.info('server stop service successfully');
338  } else {
339    console.error('server stop service failed');
340  }
341});
342```
343
344## 相关实例
345
346针对WebSocket连接的开发,有以下相关实例可供参考:
347
348- [WebSocket(ArkTS)(API9)](https://gitcode.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Connectivity/WebSocket)
349
350- [WebSocket连接](https://gitcode.com/openharmony/applications_app_samples/tree/master/code/DocsSample/NetWork_Kit/NetWorkKit_Datatransmission/WebSocket_case)
351