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