• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Socket 连接
2
3## 简介
4
5Socket 连接主要是通过 Socket 进行数据传输,支持 TCP/UDP/TLS 协议。
6
7## 基本概念
8
9- Socket:套接字,就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。
10- TCP:传输控制协议(Transmission Control Protocol)。是一种面向连接的、可靠的、基于字节流的传输层通信协议。
11- UDP:用户数据报协议(User Datagram Protocol)。是一个简单的面向消息的传输层,不需要连接。
12- TLS:安全传输层协议(Transport Layer Security)。用于在两个通信应用程序之间提供保密性和数据完整性。
13
14## 场景介绍
15
16应用通过 Socket 进行数据传输,支持 TCP/UDP/TLS 协议。主要场景有:
17
18- 应用通过 TCP/UDP Socket 进行数据传输
19- 应用通过 TCP Socket Server 进行数据传输
20- 应用通过 TLS Socket 进行加密数据传输
21
22## 接口说明
23
24完整的 JS API 说明以及实例代码请参考:[Socket 连接](../reference/apis/js-apis-socket.md)。
25
26Socket 连接主要由 socket 模块提供。具体接口说明如下表。
27
28| 接口名                             | 描述                                                                          |
29| ---------------------------------- | ------------------------------------------------------------------------------ |
30| constructUDPSocketInstance()       | 创建一个 UDPSocket 对象。                                                      |
31| constructTCPSocketInstance()       | 创建一个 TCPSocket 对象。                                                      |
32| constructTCPSocketServerInstance() | 创建一个 TCPSocketServer 对象。                                                |
33| listen()                           | 绑定 IP 地址和端口,监听并接受与此套接字建立的 TCPSocket 连接。(仅 TCP 支持)    |
34| bind()                             | 绑定 IP 地址和端口。                                                           |
35| send()                             | 发送数据。                                                                     |
36| close()                            | 关闭连接。                                                                     |
37| getState()                         | 获取 Socket 状态。                                                             |
38| connect()                          | 连接到指定的 IP 地址和端口(仅 TCP 支持)                                      |
39| getRemoteAddress()                 | 获取对端 Socket 地址(仅 TCP 支持,需要先调用 connect 方法)                   |
40| setExtraOptions()                  | 设置 Socket 连接的其他属性。                                                   |
41| on(type: 'message')           | 订阅 Socket 连接的接收消息事件。                                               |
42| off(type: 'message')          | 取消订阅 Socket 连接的接收消息事件。                                           |
43| on(type: 'close')             | 订阅 Socket 连接的关闭事件。                                                   |
44| off(type: 'close')            | 取消订阅 Socket 连接的关闭事件。                                               |
45| on(type: 'error')             | 订阅 Socket 连接的 Error 事件。                                                |
46| off(type: 'error')            | 取消订阅 Socket 连接的 Error 事件。                                            |
47| on(type: 'listening')         | 订阅 UDPSocket 连接的数据包消息事件(仅 UDP 支持)。                           |
48| off(type: 'listening')        | 取消订阅 UDPSocket 连接的数据包消息事件(仅 UDP 支持)。                       |
49| on(type: 'connect')           | 订阅 TCPSocket 的连接事件(仅 TCP 支持)。                                     |
50| off(type: 'connect')          | 取消订阅 TCPSocket 的连接事件(仅 TCP 支持)。                                 |
51
52TLS Socket 连接主要由 tls_socket 模块提供。具体接口说明如下表。
53
54| 接口名                       | 功能描述                                                   |
55| ---------------------------- | ---------------------------------------------------------- |
56| constructTLSSocketInstance() | 创建一个 TLSSocket 对象。                                  |
57| bind()                       | 绑定 IP 地址和端口号。                                     |
58| close(type: 'error')    | 关闭连接。                                                 |
59| connect()                    | 连接到指定的 IP 地址和端口。                               |
60| getCertificate()             | 返回表示本地证书的对象。                                   |
61| getCipherSuite()             | 返回包含协商的密码套件信息的列表。                         |
62| getProtocol()                | 返回包含当前连接协商的 SSL/TLS 协议版本的字符串。          |
63| getRemoteAddress()           | 获取 TLSSocket 连接的对端地址。                            |
64| getRemoteCertificate()       | 返回表示对等证书的对象。                                   |
65| getSignatureAlgorithms()     | 在服务器和客户端之间共享的签名算法列表,按优先级降序排列。 |
66| getState()                   | 获取 TLSSocket 连接的状态。                                |
67| off(type: 'close')      | 取消订阅 TLSSocket 连接的关闭事件。                        |
68| off(type: 'error')      | 取消订阅 TLSSocket 连接的 Error 事件。                     |
69| off(type: 'message')    | 取消订阅 TLSSocket 连接的接收消息事件。                    |
70| on(type: 'close')       | 订阅 TLSSocket 连接的关闭事件。                            |
71| on(type: 'error')       | 订阅 TLSSocket 连接的 Error 事件。                         |
72| on(type: 'message')     | 订阅 TLSSocket 连接的接收消息事件。                        |
73| send()                       | 发送数据。                                                 |
74| setExtraOptions()            | 设置 TLSSocket 连接的其他属性。                            |
75
76## 应用 TCP/UDP 协议进行通信
77
78UDP 与 TCP 流程大体类似,下面以 TCP 为例:
79
801. import 需要的 socket 模块。
81
822. 创建一个 TCPSocket 连接,返回一个 TCPSocket 对象。
83
843. (可选)订阅 TCPSocket 相关的订阅事件。
85
864. 绑定 IP 地址和端口,端口可以指定或由系统随机分配。
87
885. 连接到指定的 IP 地址和端口。
89
906. 发送数据。
91
927. Socket 连接使用完毕后,主动关闭。
93
94```js
95import socket from '@ohos.net.socket';
96import { BusinessError } from '@ohos.base';
97
98class SocketInfo {
99  message: ArrayBuffer = new ArrayBuffer(1);
100  remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo;
101}
102// 创建一个TCPSocket连接,返回一个TCPSocket对象。
103let tcp = socket.constructTCPSocketInstance();
104tcp.on('message', (value: SocketInfo) => {
105  console.log("on message");
106  let buffer = value.message;
107  let dataView = new DataView(buffer);
108  let str = "";
109  for (let i = 0; i < dataView.byteLength; ++i) {
110    str += String.fromCharCode(dataView.getUint8(i));
111  }
112  console.log("on connect received:" + str);
113});
114tcp.on('connect', () => {
115  console.log("on connect");
116});
117tcp.on('close', () => {
118  console.log("on close");
119});
120
121// 绑定本地IP地址和端口。
122let ipAddress : socket.NetAddress = {} as socket.NetAddress;
123ipAddress.address = "192.168.xxx.xxx";
124ipAddress.port = 1234;
125tcp.bind(ipAddress, (err: BusinessError) => {
126  if (err) {
127    console.log('bind fail');
128    return;
129  }
130  console.log('bind success');
131
132  // 连接到指定的IP地址和端口。
133  ipAddress.address = "192.168.xxx.xxx";
134  ipAddress.port = 5678;
135
136  let tcpConnect : socket.TCPConnectOptions = {} as socket.TCPConnectOptions;
137  tcpConnect.address = ipAddress;
138  tcpConnect.timeout = 6000;
139
140  tcp.connect(tcpConnect, (err: BusinessError) => {
141    if (err) {
142      console.log('connect fail');
143      return;
144    }
145    console.log('connect success');
146    // 发送数据
147    let tcpSendOptions : socket.TCPSendOptions = {} as socket.TCPSendOptions;
148    tcpSendOptions.data = 'Hello, server!';
149    tcp.send(tcpSendOptions, (err: BusinessError) => {
150      if (err) {
151        console.log('send fail');
152        return;
153      }
154      console.log('send success');
155    })
156  });
157});
158
159// 连接使用完毕后,主动关闭。取消相关事件的订阅。
160setTimeout(() => {
161  tcp.close((err: BusinessError) => {
162    console.log('close socket.');
163  });
164  tcp.off('message');
165  tcp.off('connect');
166  tcp.off('close');
167}, 30 * 1000);
168```
169
170## 应用通过 TCP Socket Server 进行数据传输
171
172### 开发步骤
173
174服务端 TCP Socket 流程:
175
1761. import 需要的 socket 模块。
1772. 创建一个 TCPSocketServer 连接,返回一个 TCPSocketServer 对象。
1783. 绑定本地 IP 地址和端口,监听并接受与此套接字建立的客户端 TCPSocket 连接。
1794. 订阅 TCPSocketServer 的 connect 事件,用于监听客户端的连接状态。
1805. 客户端与服务端建立连接后,返回一个 TCPSocketConnection 对象,用于与客户端通信。
1816. 订阅 TCPSocketConnection 相关的事件,通过 TCPSocketConnection 向客户端发送数据。
1827. 主动关闭与客户端的连接。
1838. 取消 TCPSocketConnection 和 TCPSocketServer 相关事件的订阅。
184
185```js
186import socket from '@ohos.net.socket';
187import { BusinessError } from '@ohos.base';
188// 创建一个TCPSocketServer连接,返回一个TCPSocketServer对象。
189let tcpServer = socket.constructTCPSocketServerInstance();
190// 绑定本地IP地址和端口,进行监听
191
192let ipAddress : socket.NetAddress = {} as socket.NetAddress;
193ipAddress.address = "192.168.xxx.xxx";
194ipAddress.port = 4651;
195tcpServer.listen(ipAddress, (err: BusinessError) => {
196  if (err) {
197    console.log("listen fail");
198    return;
199  }
200  console.log("listen success");
201});
202
203class SocketInfo {
204  message: ArrayBuffer = new ArrayBuffer(1);
205  remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo;
206}
207// 订阅TCPSocketServer的connect事件
208tcpServer.on("connect", (client: socket.TCPSocketConnection) => {
209  // 订阅TCPSocketConnection相关的事件
210  client.on("close", () => {
211    console.log("on close success");
212  });
213  client.on("message", (value: SocketInfo) => {
214    let buffer = value.message;
215    let dataView = new DataView(buffer);
216    let str = "";
217    for (let i = 0; i < dataView.byteLength; ++i) {
218      str += String.fromCharCode(dataView.getUint8(i));
219    }
220    console.log("received message--:" + str);
221    console.log("received address--:" + value.remoteInfo.address);
222    console.log("received family--:" + value.remoteInfo.family);
223    console.log("received port--:" + value.remoteInfo.port);
224    console.log("received size--:" + value.remoteInfo.size);
225  });
226
227  // 向客户端发送数据
228  let tcpSendOptions : socket.TCPSendOptions = {} as socket.TCPSendOptions;
229  tcpSendOptions.data = 'Hello, client!';
230  client.send(tcpSendOptions, (err: BusinessError) => {
231    if (err) {
232      console.log("send fail");
233      return;
234    }
235    console.log("send success");
236  });
237
238  // 关闭与客户端的连接
239  client.close((err: BusinessError) => {
240    if (err) {
241      console.log("close fail");
242      return;
243    }
244    console.log("close success");
245  });
246
247  // 取消TCPSocketConnection相关的事件订阅
248  setTimeout(() => {
249    client.off("message");
250    client.off("close");
251  }, 10 * 1000);
252});
253
254// 取消TCPSocketServer相关的事件订阅
255setTimeout(() => {
256  tcpServer.off("connect");
257}, 30 * 1000);
258```
259
260## 应用通过 TLS Socket 进行加密数据传输
261
262### 开发步骤
263
264客户端 TLS Socket 流程:
265
2661. import 需要的 socket 模块。
267
2682. 绑定服务器 IP 和端口号。
269
2703. 双向认证上传客户端 CA 证书及数字证书;单向认证上传客户端 CA 证书。
271
2724. 创建一个 TLSSocket 连接,返回一个 TLSSocket 对象。
273
2745. (可选)订阅 TLSSocket 相关的订阅事件。
275
2766. 发送数据。
277
2787. TLSSocket 连接使用完毕后,主动关闭。
279
280```js
281import socket from '@ohos.net.socket';
282import { BusinessError } from '@ohos.base';
283
284class SocketInfo {
285  message: ArrayBuffer = new ArrayBuffer(1);
286  remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo;
287}
288// 创建一个(双向认证)TLS Socket连接,返回一个TLS Socket对象。
289let tlsTwoWay = socket.constructTLSSocketInstance();
290// 订阅TLS Socket相关的订阅事件
291tlsTwoWay.on('message', (value: SocketInfo) => {
292  console.log("on message");
293  let buffer = value.message;
294  let dataView = new DataView(buffer);
295  let str = "";
296  for (let i = 0; i < dataView.byteLength; ++i) {
297    str += String.fromCharCode(dataView.getUint8(i));
298  }
299  console.log("on connect received:" + str);
300});
301tlsTwoWay.on('connect', () => {
302  console.log("on connect");
303});
304tlsTwoWay.on('close', () => {
305  console.log("on close");
306});
307
308// 绑定本地IP地址和端口。
309let ipAddress : socket.NetAddress = {} as socket.NetAddress;
310ipAddress.address = "192.168.xxx.xxx";
311ipAddress.port = 4512;
312tlsTwoWay.bind(ipAddress, (err: BusinessError) => {
313  if (err) {
314    console.log('bind fail');
315    return;
316  }
317  console.log('bind success');
318});
319
320ipAddress.address = "192.168.xxx.xxx";
321ipAddress.port = 1234;
322
323let tlsSecureOption : socket.TLSSecureOptions = {} as socket.TLSSecureOptions;
324tlsSecureOption.key = "xxxx";
325tlsSecureOption.cert = "xxxx";
326tlsSecureOption.ca = ["xxxx"];
327tlsSecureOption.password = "xxxx";
328tlsSecureOption.protocols = [socket.Protocol.TLSv12];
329tlsSecureOption.useRemoteCipherPrefer = true;
330tlsSecureOption.signatureAlgorithms = "rsa_pss_rsae_sha256:ECDSA+SHA256";
331tlsSecureOption.cipherSuite = "AES256-SHA256";
332
333let tlsTwoWayConnectOption : socket.TLSConnectOptions = {} as socket.TLSConnectOptions;
334tlsSecureOption.key = "xxxx";
335tlsTwoWayConnectOption.address = ipAddress;
336tlsTwoWayConnectOption.secureOptions = tlsSecureOption;
337tlsTwoWayConnectOption.ALPNProtocols = ["spdy/1", "http/1.1"];
338
339// 建立连接
340tlsTwoWay.connect(tlsTwoWayConnectOption, () => {
341  console.error("connect function");
342});
343
344// 连接使用完毕后,主动关闭。取消相关事件的订阅。
345tlsTwoWay.close((err: BusinessError) => {
346  if (err) {
347    console.log("close callback error = " + err);
348  } else {
349    console.log("close success");
350  }
351  tlsTwoWay.off('message');
352  tlsTwoWay.off('connect');
353  tlsTwoWay.off('close');
354});
355
356// 创建一个(单向认证)TLS Socket连接,返回一个TLS Socket对象。
357let tlsOneWay = socket.constructTLSSocketInstance(); // One way authentication
358
359// 订阅TLS Socket相关的订阅事件
360tlsTwoWay.on('message', (value: SocketInfo) => {
361  console.log("on message");
362  let buffer = value.message;
363  let dataView = new DataView(buffer);
364  let str = "";
365  for (let i = 0; i < dataView.byteLength; ++i) {
366    str += String.fromCharCode(dataView.getUint8(i));
367  }
368  console.log("on connect received:" + str);
369});
370tlsTwoWay.on('connect', () => {
371  console.log("on connect");
372});
373tlsTwoWay.on('close', () => {
374  console.log("on close");
375});
376
377// 绑定本地IP地址和端口。
378ipAddress.address = "192.168.xxx.xxx";
379ipAddress.port = 5445;
380tlsOneWay.bind(ipAddress, (err:BusinessError) => {
381  if (err) {
382    console.log('bind fail');
383    return;
384  }
385  console.log('bind success');
386});
387
388ipAddress.address = "192.168.xxx.xxx";
389ipAddress.port = 8789;
390let tlsOneWaySecureOption : socket.TLSSecureOptions = {} as socket.TLSSecureOptions;
391tlsOneWaySecureOption.ca = ["xxxx", "xxxx"];
392tlsOneWaySecureOption.cipherSuite = "AES256-SHA256";
393
394let tlsOneWayConnectOptions: socket.TLSConnectOptions = {} as socket.TLSConnectOptions;
395tlsOneWayConnectOptions.address = ipAddress;
396tlsOneWayConnectOptions.secureOptions = tlsOneWaySecureOption;
397
398// 建立连接
399tlsOneWay.connect(tlsOneWayConnectOptions, () => {
400  console.error("connect function");
401});
402
403// 连接使用完毕后,主动关闭。取消相关事件的订阅。
404tlsTwoWay.close((err: BusinessError) => {
405  if (err) {
406    console.log("close callback error = " + err);
407  } else {
408    console.log("close success");
409  }
410  tlsTwoWay.off('message');
411  tlsTwoWay.off('connect');
412  tlsTwoWay.off('close');
413});
414```
415
416## 相关实例
417
418针对 Socket 连接开发,有以下相关实例可供参考:
419
420- [网络管理-Socket 连接(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/OpenHarmony-4.0-Release/code/BasicFeature/Connectivity/Socket)
421