1# Socket 连接 2 3## 简介 4 5Socket 连接主要是通过 Socket 进行数据传输,支持 TCP/UDP/Multicast/TLS 协议。 6 7> **说明:** 8> 9> 应用退后台又切回前台后,需要对网络通信做失败重试,通信失败后匹配错误码并重新创建新的TCP/UDP连接对象。 10 11## 基本概念 12 13- Socket:套接字,就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。 14- TCP:传输控制协议(Transmission Control Protocol)。是一种面向连接的、可靠的、基于字节流的传输层通信协议。 15- UDP:用户数据报协议(User Datagram Protocol)。是一个简单的面向消息的传输层,不需要连接。 16- Multicast:多播,基于UDP的一种通信模式,用于实现组内所有设备之间广播形式的通信。 17- LocalSocket:本地套接字,IPC(Inter-Process Communication)进程间通信的一种,实现设备内进程之间相互通信,无需网络。 18- TLS:安全传输层协议(Transport Layer Security)。用于在两个通信应用程序之间提供保密性和数据完整性。 19 20## 场景介绍 21 22应用通过 Socket 进行数据传输,支持 TCP/UDP/Multicast/TLS 协议。主要场景有: 23 24- 应用通过 TCP/UDP Socket进行数据传输 25- 应用通过 TCP Socket Server 进行数据传输 26- 应用通过 Multicast Socket 进行数据传输 27- 应用通过 Local Socket进行数据传输 28- 应用通过 Local Socket Server 进行数据传输 29- 应用通过 TLS Socket 进行加密数据传输 30- 应用通过 TLS Socket Server 进行加密数据传输 31 32## 接口说明 33 34完整的 API 说明以及实例代码请参考:[Socket 连接](../reference/apis-network-kit/js-apis-socket.md)。 35 36Socket 连接主要由 socket 模块提供。具体接口说明如下表。 37 38| 接口名 | 描述 | 39| ---------------------------------- | ------------------------------------------------------------------------------ | 40| constructUDPSocketInstance() | 创建一个 UDPSocket 对象。 | 41| constructTCPSocketInstance() | 创建一个 TCPSocket 对象。 | 42| constructTCPSocketServerInstance() | 创建一个 TCPSocketServer 对象。 | 43| constructMulticastSocketInstance() | 创建一个 MulticastSocket 对象。 | 44| constructLocalSocketInstance() | 创建一个 LocalSocket 对象。 | 45| constructLocalSocketServerInstance() | 创建一个 LocalSocketServer 对象。 | 46| listen() | 绑定、监听并启动服务,接收客户端的连接请求。(仅 TCP/LocalSocket 支持)。 | 47| bind() | 绑定 IP 地址和端口,或是绑定本地套接字路径。 | 48| send() | 发送数据。 | 49| close() | 关闭连接。 | 50| getState() | 获取 Socket 状态。 | 51| connect() | 连接到指定的 IP 地址和端口,或是连接到本地套接字(仅 TCP/LocalSocket 支持)。 | 52| getRemoteAddress() | 获取对端 Socket 地址(仅 TCP 支持,需要先调用 connect 方法)。 | 53| setExtraOptions() | 设置 Socket 连接的其他属性。 | 54| getExtraOptions() | 获取 Socket 连接的其他属性(仅 LocalSocket 支持)。 | 55| addMembership() | 加入到指定的多播组 IP 中 (仅 Multicast 支持)。 | 56| dropMembership() | 从指定的多播组 IP 中退出 (仅 Multicast 支持)。 | 57| setMulticastTTL() | 设置数据传输跳数 TTL (仅 Multicast 支持)。 | 58| getMulticastTTL() | 获取数据传输跳数 TTL (仅 Multicast 支持)。 | 59| setLoopbackMode() | 设置回环模式,允许主机在本地循环接收自己发送的多播数据包 (仅 Multicast 支持)。 | 60| getLoopbackMode() | 获取回环模式开启或关闭的状态 (仅 Multicast 支持)。 | 61| on(type: 'message') | 订阅 Socket 连接的接收消息事件。 | 62| off(type: 'message') | 取消订阅 Socket 连接的接收消息事件。 | 63| on(type: 'close') | 订阅 Socket 连接的关闭事件。 | 64| off(type: 'close') | 取消订阅 Socket 连接的关闭事件。 | 65| on(type: 'error') | 订阅 Socket 连接的 Error 事件。 | 66| off(type: 'error') | 取消订阅 Socket 连接的 Error 事件。 | 67| on(type: 'listening') | 订阅 UDPSocket 连接的数据包消息事件(仅 UDP 支持)。 | 68| off(type: 'listening') | 取消订阅 UDPSocket 连接的数据包消息事件(仅 UDP 支持)。 | 69| on(type: 'connect') | 订阅 Socket 的连接事件(仅 TCP/LocalSocket 支持)。 | 70| off(type: 'connect') | 取消订阅 Socket 的连接事件(仅 TCP/LocalSocket 支持)。 | 71 72TLS Socket 连接主要由 tls_socket 模块提供。具体接口说明如下表。 73 74| 接口名 | 功能描述 | 75| ---------------------------- | ---------------------------------------------------------- | 76| constructTLSSocketInstance() | 创建一个 TLSSocket 对象。 | 77| bind() | 绑定 IP 地址和端口号。 | 78| close(type: 'error') | 关闭连接。 | 79| connect() | 连接到指定的 IP 地址和端口。 | 80| getCertificate() | 返回表示本地证书的对象。 | 81| getCipherSuite() | 返回包含协商的密码套件信息的列表。 | 82| getProtocol() | 返回包含当前连接协商的 SSL/TLS 协议版本的字符串。 | 83| getRemoteAddress() | 获取 TLSSocket 连接的对端地址。 | 84| getRemoteCertificate() | 返回表示对等证书的对象。 | 85| getSignatureAlgorithms() | 在服务器和客户端之间共享的签名算法列表,按优先级降序排列。 | 86| getState() | 获取 TLSSocket 连接的状态。 | 87| off(type: 'close') | 取消订阅 TLSSocket 连接的关闭事件。 | 88| off(type: 'error') | 取消订阅 TLSSocket 连接的 Error 事件。 | 89| off(type: 'message') | 取消订阅 TLSSocket 连接的接收消息事件。 | 90| on(type: 'close') | 订阅 TLSSocket 连接的关闭事件。 | 91| on(type: 'error') | 订阅 TLSSocket 连接的 Error 事件。 | 92| on(type: 'message') | 订阅 TLSSocket 连接的接收消息事件。 | 93| send() | 发送数据。 | 94| setExtraOptions() | 设置 TLSSocket 连接的其他属性。 | 95 96## 应用 TCP/UDP 协议进行通信 97 98UDP 与 TCP 流程大体类似,下面以 TCP 为例: 99 1001. import 需要的 socket 模块。 101 1022. 创建一个 TCPSocket 连接,返回一个 TCPSocket 对象。 103 1043. (可选)订阅 TCPSocket 相关的订阅事件。 105 1064. 绑定 IP 地址和端口,端口可以指定或由系统随机分配。 107 1085. 连接到指定的 IP 地址和端口。 109 1106. 发送数据。 111 1127. Socket 连接使用完毕后,主动关闭。 113 114```ts 115import { socket } from '@kit.NetworkKit'; 116import { BusinessError } from '@kit.BasicServicesKit'; 117 118class SocketInfo { 119 message: ArrayBuffer = new ArrayBuffer(1); 120 remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo; 121} 122// 创建一个TCPSocket连接,返回一个TCPSocket对象。 123let tcp: socket.TCPSocket = socket.constructTCPSocketInstance(); 124tcp.on('message', (value: SocketInfo) => { 125 console.log("on message"); 126 let buffer = value.message; 127 let dataView = new DataView(buffer); 128 let str = ""; 129 for (let i = 0; i < dataView.byteLength; ++i) { 130 str += String.fromCharCode(dataView.getUint8(i)); 131 } 132 console.log("on connect received:" + str); 133}); 134tcp.on('connect', () => { 135 console.log("on connect"); 136}); 137tcp.on('close', () => { 138 console.log("on close"); 139}); 140 141// 绑定本地IP地址和端口。 142let ipAddress : socket.NetAddress = {} as socket.NetAddress; 143ipAddress.address = "192.168.xxx.xxx"; 144ipAddress.port = 1234; 145tcp.bind(ipAddress, (err: BusinessError) => { 146 if (err) { 147 console.log('bind fail'); 148 return; 149 } 150 console.log('bind success'); 151 152 // 连接到指定的IP地址和端口。 153 ipAddress.address = "192.168.xxx.xxx"; 154 ipAddress.port = 5678; 155 156 let tcpConnect : socket.TCPConnectOptions = {} as socket.TCPConnectOptions; 157 tcpConnect.address = ipAddress; 158 tcpConnect.timeout = 6000; 159 160 tcp.connect(tcpConnect).then(() => { 161 console.log('connect success'); 162 let tcpSendOptions: socket.TCPSendOptions = { 163 data: 'Hello, server!' 164 } 165 tcp.send(tcpSendOptions).then(() => { 166 console.log('send success'); 167 }).catch((err: BusinessError) => { 168 console.log('send fail'); 169 }); 170 }).catch((err: BusinessError) => { 171 console.log('connect fail'); 172 }); 173}); 174 175// 连接使用完毕后,主动关闭。取消相关事件的订阅。 176setTimeout(() => { 177 tcp.close().then(() => { 178 console.log('close success'); 179 }).catch((err: BusinessError) => { 180 console.log('close fail'); 181 }); 182 tcp.off('message'); 183 tcp.off('connect'); 184 tcp.off('close'); 185}, 30 * 1000); 186``` 187 188## 应用通过 TCP Socket Server 进行数据传输 189 190服务端 TCP Socket 流程: 191 1921. import 需要的 socket 模块。 1932. 创建一个 TCPSocketServer 连接,返回一个 TCPSocketServer 对象。 1943. 绑定本地 IP 地址和端口,监听并接受与此套接字建立的客户端 TCPSocket 连接。 1954. 订阅 TCPSocketServer 的 connect 事件,用于监听客户端的连接状态。 1965. 客户端与服务端建立连接后,返回一个 TCPSocketConnection 对象,用于与客户端通信。 1976. 订阅 TCPSocketConnection 相关的事件,通过 TCPSocketConnection 向客户端发送数据。 1987. 主动关闭与客户端的连接。 1998. 取消 TCPSocketConnection 和 TCPSocketServer 相关事件的订阅。 200 201```ts 202import { socket } from '@kit.NetworkKit'; 203import { BusinessError } from '@kit.BasicServicesKit'; 204 205// 创建一个TCPSocketServer连接,返回一个TCPSocketServer对象。 206let tcpServer: socket.TCPSocketServer = socket.constructTCPSocketServerInstance(); 207// 绑定本地IP地址和端口,进行监听 208 209let ipAddress : socket.NetAddress = {} as socket.NetAddress; 210ipAddress.address = "192.168.xxx.xxx"; 211ipAddress.port = 4651; 212tcpServer.listen(ipAddress).then(() => { 213 console.log('listen success'); 214}).catch((err: BusinessError) => { 215 console.log('listen fail'); 216}); 217 218class SocketInfo { 219 message: ArrayBuffer = new ArrayBuffer(1); 220 remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo; 221} 222// 订阅TCPSocketServer的connect事件 223tcpServer.on("connect", (client: socket.TCPSocketConnection) => { 224 // 订阅TCPSocketConnection相关的事件 225 client.on("close", () => { 226 console.log("on close success"); 227 }); 228 client.on("message", (value: SocketInfo) => { 229 let buffer = value.message; 230 let dataView = new DataView(buffer); 231 let str = ""; 232 for (let i = 0; i < dataView.byteLength; ++i) { 233 str += String.fromCharCode(dataView.getUint8(i)); 234 } 235 console.log("received message--:" + str); 236 console.log("received address--:" + value.remoteInfo.address); 237 console.log("received family--:" + value.remoteInfo.family); 238 console.log("received port--:" + value.remoteInfo.port); 239 console.log("received size--:" + value.remoteInfo.size); 240 }); 241 242 // 向客户端发送数据 243 let tcpSendOptions : socket.TCPSendOptions = {} as socket.TCPSendOptions; 244 tcpSendOptions.data = 'Hello, client!'; 245 client.send(tcpSendOptions).then(() => { 246 console.log('send success'); 247 }).catch((err: Object) => { 248 console.error('send fail: ' + JSON.stringify(err)); 249 }); 250 251 // 关闭与客户端的连接 252 client.close().then(() => { 253 console.log('close success'); 254 }).catch((err: BusinessError) => { 255 console.log('close fail'); 256 }); 257 258 // 取消TCPSocketConnection相关的事件订阅 259 setTimeout(() => { 260 client.off("message"); 261 client.off("close"); 262 }, 10 * 1000); 263}); 264 265// 取消TCPSocketServer相关的事件订阅 266setTimeout(() => { 267 tcpServer.off("connect"); 268}, 30 * 1000); 269``` 270 271## 应用通过 Multicast Socket 进行数据传输 272 2731. import 需要的 socket 模块。 274 2752. 创建 multicastSocket 多播对象。 276 2773. 指定多播 IP 与端口,加入多播组。 278 2794. 开启消息 message 监听。 280 2815. 发送数据,数据以广播的形式传输,同一多播组中已经开启消息 message 监听的多播对象都会接收到数据。 282 2836. 关闭 message 消息的监听。 284 2857. 退出多播组。 286 287```ts 288import { socket } from '@kit.NetworkKit'; 289 290// 创建Multicast对象 291let multicast: socket.MulticastSocket = socket.constructMulticastSocketInstance(); 292 293let addr : socket.NetAddress = { 294 address: '239.255.0.1', 295 port: 32123, 296 family: 1 297} 298 299// 加入多播组 300multicast.addMembership(addr).then(() => { 301 console.log('addMembership success'); 302}).catch((err: Object) => { 303 console.log('addMembership fail'); 304}); 305 306// 开启监听消息数据,将接收到的ArrayBuffer类型数据转换为String 307class SocketInfo { 308 message: ArrayBuffer = new ArrayBuffer(1); 309 remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo; 310} 311multicast.on('message', (data: SocketInfo) => { 312 console.info('接收的数据: ' + JSON.stringify(data)) 313 const uintArray = new Uint8Array(data.message) 314 let str = '' 315 for (let i = 0; i < uintArray.length; ++i) { 316 str += String.fromCharCode(uintArray[i]) 317 } 318 console.info(str) 319}) 320 321// 发送数据 322multicast.send({ data:'Hello12345', address: addr }).then(() => { 323 console.log('send success'); 324}).catch((err: Object) => { 325 console.log('send fail, ' + JSON.stringify(err)); 326}); 327 328// 关闭消息的监听 329multicast.off('message') 330 331// 退出多播组 332multicast.dropMembership(addr).then(() => { 333 console.log('drop membership success'); 334}).catch((err: Object) => { 335 console.log('drop membership fail'); 336}); 337``` 338 339## 应用通过 LocalSocket 进行数据传输 340 3411. import 需要的 socket 模块。 342 3432. 使用 constructLocalSocketInstance 接口,创建一个 LocalSocket 客户端对象。 344 3453. 注册 LocalSocket 的消息(message)事件,以及一些其它事件(可选)。 346 3474. 连接到指定的本地套接字文件路径。 348 3495. 发送数据。 350 3516. Socket 连接使用完毕后,取消事件的注册,并关闭套接字。 352 353**注意:** 关于示例代码中this的说明:在本文档的示例中,通过this.context来获取UIAbilityContext,其中this代表继承自UIAbility的UIAbility实例。如需在页面中使用UIAbilityContext提供的能力,[请参见获取UIAbility的上下文消息](http://gitee.com/openharmony/docs/blob/222f8d93e6f0056409aac096e041df3fdd8ae5ec/zh-cn/application-dev/application-models/uiability-usage.md)。 354 355```ts 356import { socket } from '@kit.NetworkKit'; 357import { common } from '@kit.AbilityKit'; 358 359// 创建一个LocalSocket连接,返回一个LocalSocket对象。 360let client: socket.LocalSocket = socket.constructLocalSocketInstance(); 361client.on('message', (value: socket.LocalSocketMessageInfo) => { 362 const uintArray = new Uint8Array(value.message) 363 let messageView = ''; 364 for (let i = 0; i < uintArray.length; i++) { 365 messageView += String.fromCharCode(uintArray[i]); 366 } 367 console.log('total receive: ' + JSON.stringify(value)); 368 console.log('message information: ' + messageView); 369}); 370client.on('connect', () => { 371 console.log("on connect"); 372}); 373client.on('close', () => { 374 console.log("on close"); 375}); 376 377// 传入指定的本地套接字路径,连接服务端。 378let context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext; 379let sandboxPath: string = context.filesDir + '/testSocket'; 380let localAddress : socket.LocalAddress = { 381 address: sandboxPath 382} 383let connectOpt: socket.LocalConnectOptions = { 384 address: localAddress, 385 timeout: 6000 386} 387let sendOpt: socket.LocalSendOptions = { 388 data: 'Hello world!' 389} 390client.connect(connectOpt).then(() => { 391 console.log('connect success') 392 client.send(sendOpt).then(() => { 393 console.log('send success') 394 }).catch((err: Object) => { 395 console.log('send failed: ' + JSON.stringify(err)) 396 }) 397}).catch((err: Object) => { 398 console.log('connect fail: ' + JSON.stringify(err)); 399}); 400 401// 当不需要再连接服务端,需要断开且取消事件的监听时 402client.off('message'); 403client.off('connect'); 404client.off('close'); 405client.close().then(() => { 406 console.log('close client success') 407}).catch((err: Object) => { 408 console.log('close client err: ' + JSON.stringify(err)) 409}) 410``` 411 412## 应用通过 Local Socket Server 进行数据传输 413 414服务端 LocalSocket Server 流程: 415 4161. import 需要的 socket 模块。 417 4182. 使用 constructLocalSocketServerInstance 接口,创建一个 LocalSocketServer 服务端对象。 419 4203. 启动服务,绑定本地套接字路径,创建出本地套接字文件,监听客户端的连接请求。 421 4224. 注册 LocalSocket 的客户端连接(connect)事件,以及一些其它事件(可选)。 423 4245. 在客户端连接上来时,通过连接事件的回调函数,获取连接会话对象。 425 4266. 给会话对象 LocalSocketConnection 注册消息(message)事件,以及一些其它事件(可选)。 427 4287. 通过会话对象主动向客户端发送消息。 429 4308. 结束与客户端的通信,主动断开与客户端的连接。 431 4329. 取消 LocalSocketConnection 和 LocalSocketServer 相关事件的订阅。 433 434**注意:** 关于示例代码中this的说明:在本文档的示例中,通过this.context来获取UIAbilityContext,其中this代表继承自UIAbility的UIAbility实例。如需在页面中使用UIAbilityContext提供的能力,[请参见获取UIAbility的上下文消息](http://gitee.com/openharmony/docs/blob/222f8d93e6f0056409aac096e041df3fdd8ae5ec/zh-cn/application-dev/application-models/uiability-usage.md)。 435 436```ts 437import { socket } from '@kit.NetworkKit'; 438import { common } from '@kit.AbilityKit'; 439 440// 创建一个LocalSocketServer连接,返回一个LocalSocketServer对象。 441let server: socket.LocalSocketServer = socket.constructLocalSocketServerInstance(); 442// 创建并绑定本地套接字文件testSocket,进行监听 443let context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext; 444let sandboxPath: string = context.filesDir + '/testSocket'; 445let listenAddr: socket.LocalAddress = { 446 address: sandboxPath 447} 448server.listen(listenAddr).then(() => { 449 console.log("listen success"); 450}).catch((err: Object) => { 451 console.log("listen fail: " + JSON.stringify(err)); 452}); 453 454// 订阅LocalSocketServer的connect事件 455server.on('connect', (connection: socket.LocalSocketConnection) => { 456 // 订阅LocalSocketConnection相关的事件 457 connection.on('error', (err: Object) => { 458 console.log("on error success"); 459 }); 460 connection.on('message', (value: socket.LocalSocketMessageInfo) => { 461 const uintArray = new Uint8Array(value.message); 462 let messageView = ''; 463 for (let i = 0; i < uintArray.length; i++) { 464 messageView += String.fromCharCode(uintArray[i]); 465 } 466 console.log('total: ' + JSON.stringify(value)); 467 console.log('message information: ' + messageView); 468 }); 469 470 connection.on('error', (err: Object) => { 471 console.log("err:" + JSON.stringify(err)); 472 }) 473 474 // 向客户端发送数据 475 let sendOpt : socket.LocalSendOptions = { 476 data: 'Hello world!' 477 }; 478 connection.send(sendOpt).then(() => { 479 console.log('send success'); 480 }).catch((err: Object) => { 481 console.log('send failed: ' + JSON.stringify(err)); 482 }) 483 484 // 关闭与客户端的连接 485 connection.close().then(() => { 486 console.log('close success'); 487 }).catch((err: Object) => { 488 console.log('close failed: ' + JSON.stringify(err)); 489 }); 490 491 // 取消LocalSocketConnection相关的事件订阅 492 connection.off('message'); 493 connection.off('error'); 494}); 495 496// 取消LocalSocketServer相关的事件订阅 497server.off('connect'); 498server.off('error'); 499``` 500 501## 应用通过 TLS Socket 进行加密数据传输 502 503客户端 TLS Socket 流程: 504 5051. import 需要的 socket 模块。 506 5072. 绑定服务器 IP 和端口号。 508 5093. 双向认证上传客户端 CA 证书及数字证书;单向认证上传客户端 CA 证书。 510 5114. 创建一个 TLSSocket 连接,返回一个 TLSSocket 对象。 512 5135. (可选)订阅 TLSSocket 相关的订阅事件。 514 5156. 发送数据。 516 5177. TLSSocket 连接使用完毕后,主动关闭。 518 519```ts 520import { socket } from '@kit.NetworkKit'; 521import { BusinessError } from '@kit.BasicServicesKit'; 522 523class SocketInfo { 524 message: ArrayBuffer = new ArrayBuffer(1); 525 remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo; 526} 527// 创建一个(双向认证)TLS Socket连接,返回一个TLS Socket对象。 528let tlsTwoWay: socket.TLSSocket = socket.constructTLSSocketInstance(); 529// 订阅TLS Socket相关的订阅事件 530tlsTwoWay.on('message', (value: SocketInfo) => { 531 console.log("on message"); 532 let buffer = value.message; 533 let dataView = new DataView(buffer); 534 let str = ""; 535 for (let i = 0; i < dataView.byteLength; ++i) { 536 str += String.fromCharCode(dataView.getUint8(i)); 537 } 538 console.log("on connect received:" + str); 539}); 540tlsTwoWay.on('connect', () => { 541 console.log("on connect"); 542}); 543tlsTwoWay.on('close', () => { 544 console.log("on close"); 545}); 546 547// 绑定本地IP地址和端口。 548let ipAddress : socket.NetAddress = {} as socket.NetAddress; 549ipAddress.address = "192.168.xxx.xxx"; 550ipAddress.port = 4512; 551tlsTwoWay.bind(ipAddress, (err: BusinessError) => { 552 if (err) { 553 console.log('bind fail'); 554 return; 555 } 556 console.log('bind success'); 557}); 558 559ipAddress.address = "192.168.xxx.xxx"; 560ipAddress.port = 1234; 561 562let tlsSecureOption : socket.TLSSecureOptions = {} as socket.TLSSecureOptions; 563tlsSecureOption.key = "xxxx"; 564tlsSecureOption.cert = "xxxx"; 565tlsSecureOption.ca = ["xxxx"]; 566tlsSecureOption.password = "xxxx"; 567tlsSecureOption.protocols = [socket.Protocol.TLSv12]; 568tlsSecureOption.useRemoteCipherPrefer = true; 569tlsSecureOption.signatureAlgorithms = "rsa_pss_rsae_sha256:ECDSA+SHA256"; 570tlsSecureOption.cipherSuite = "AES256-SHA256"; 571 572let tlsTwoWayConnectOption : socket.TLSConnectOptions = {} as socket.TLSConnectOptions; 573tlsSecureOption.key = "xxxx"; 574tlsTwoWayConnectOption.address = ipAddress; 575tlsTwoWayConnectOption.secureOptions = tlsSecureOption; 576tlsTwoWayConnectOption.ALPNProtocols = ["spdy/1", "http/1.1"]; 577 578// 建立连接 579tlsTwoWay.connect(tlsTwoWayConnectOption).then(() => { 580 console.log("connect successfully"); 581}).catch((err: BusinessError) => { 582 console.log("connect failed " + JSON.stringify(err)); 583}); 584 585// 连接使用完毕后,主动关闭。取消相关事件的订阅。 586tlsTwoWay.close((err: BusinessError) => { 587 if (err) { 588 console.log("close callback error = " + err); 589 } else { 590 console.log("close success"); 591 } 592 tlsTwoWay.off('message'); 593 tlsTwoWay.off('connect'); 594 tlsTwoWay.off('close'); 595}); 596 597// 创建一个(单向认证)TLS Socket连接,返回一个TLS Socket对象。 598let tlsOneWay: socket.TLSSocket = socket.constructTLSSocketInstance(); // One way authentication 599 600// 订阅TLS Socket相关的订阅事件 601tlsTwoWay.on('message', (value: SocketInfo) => { 602 console.log("on message"); 603 let buffer = value.message; 604 let dataView = new DataView(buffer); 605 let str = ""; 606 for (let i = 0; i < dataView.byteLength; ++i) { 607 str += String.fromCharCode(dataView.getUint8(i)); 608 } 609 console.log("on connect received:" + str); 610}); 611tlsTwoWay.on('connect', () => { 612 console.log("on connect"); 613}); 614tlsTwoWay.on('close', () => { 615 console.log("on close"); 616}); 617 618// 绑定本地IP地址和端口。 619ipAddress.address = "192.168.xxx.xxx"; 620ipAddress.port = 5445; 621tlsOneWay.bind(ipAddress, (err:BusinessError) => { 622 if (err) { 623 console.log('bind fail'); 624 return; 625 } 626 console.log('bind success'); 627}); 628 629ipAddress.address = "192.168.xxx.xxx"; 630ipAddress.port = 8789; 631let tlsOneWaySecureOption : socket.TLSSecureOptions = {} as socket.TLSSecureOptions; 632tlsOneWaySecureOption.ca = ["xxxx", "xxxx"]; 633tlsOneWaySecureOption.cipherSuite = "AES256-SHA256"; 634 635let tlsOneWayConnectOptions: socket.TLSConnectOptions = {} as socket.TLSConnectOptions; 636tlsOneWayConnectOptions.address = ipAddress; 637tlsOneWayConnectOptions.secureOptions = tlsOneWaySecureOption; 638 639// 建立连接 640tlsOneWay.connect(tlsOneWayConnectOptions).then(() => { 641 console.log("connect successfully"); 642}).catch((err: BusinessError) => { 643 console.log("connect failed " + JSON.stringify(err)); 644}); 645 646// 连接使用完毕后,主动关闭。取消相关事件的订阅。 647tlsTwoWay.close((err: BusinessError) => { 648 if (err) { 649 console.log("close callback error = " + err); 650 } else { 651 console.log("close success"); 652 } 653 tlsTwoWay.off('message'); 654 tlsTwoWay.off('connect'); 655 tlsTwoWay.off('close'); 656}); 657``` 658 659## 应用通过将 TCP Socket 升级为 TLS Socket 进行加密数据传输 660 661客户端 TCP Socket 升级为 TLS Socket 流程: 662 6631. import 需要的 socket 模块。 664 6652. 参考[应用 TCP/UDP 协议进行通信](#应用-tcpudp-协议进行通信),创建一个 TCPSocket 连接。 666 6673. 确保 TCPSocket 已连接后,使用该 TCPSocket 对象创建 TLSSocket 连接,返回一个 TLSSocket 对象。 668 6694. 双向认证上传客户端 CA 证书及数字证书;单向认证上传客户端 CA 证书。 670 6715. (可选)订阅 TLSSocket 相关的订阅事件。 672 6736. 发送数据。 674 6757. TLSSocket 连接使用完毕后,主动关闭。 676 677```ts 678import { socket } from '@kit.NetworkKit'; 679import { BusinessError } from '@kit.BasicServicesKit'; 680 681class SocketInfo { 682 message: ArrayBuffer = new ArrayBuffer(1); 683 remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo; 684} 685 686// 创建一个TCPSocket连接,返回一个TCPSocket对象。 687let tcp: socket.TCPSocket = socket.constructTCPSocketInstance(); 688tcp.on('message', (value: SocketInfo) => { 689 console.log("on message"); 690 let buffer = value.message; 691 let dataView = new DataView(buffer); 692 let str = ""; 693 for (let i = 0; i < dataView.byteLength; ++i) { 694 str += String.fromCharCode(dataView.getUint8(i)); 695 } 696 console.log("on connect received:" + str); 697}); 698tcp.on('connect', () => { 699 console.log("on connect"); 700}); 701 702// 绑定本地IP地址和端口。 703let ipAddress: socket.NetAddress = {} as socket.NetAddress; 704ipAddress.address = "192.168.xxx.xxx"; 705ipAddress.port = 1234; 706tcp.bind(ipAddress, (err: BusinessError) => { 707 if (err) { 708 console.log('bind fail'); 709 return; 710 } 711 console.log('bind success'); 712 713 // 连接到指定的IP地址和端口。 714 ipAddress.address = "192.168.xxx.xxx"; 715 ipAddress.port = 443; 716 717 let tcpConnect: socket.TCPConnectOptions = {} as socket.TCPConnectOptions; 718 tcpConnect.address = ipAddress; 719 tcpConnect.timeout = 6000; 720 721 tcp.connect(tcpConnect, (err: BusinessError) => { 722 if (err) { 723 console.log('connect fail'); 724 return; 725 } 726 console.log('connect success'); 727 728 // 确保TCPSocket已连接后,将其升级为TLSSocket连接。 729 let tlsTwoWay: socket.TLSSocket = socket.constructTLSSocketInstance(tcp); 730 // 订阅TLSSocket相关的订阅事件。 731 tlsTwoWay.on('message', (value: SocketInfo) => { 732 console.log("tls on message"); 733 let buffer = value.message; 734 let dataView = new DataView(buffer); 735 let str = ""; 736 for (let i = 0; i < dataView.byteLength; ++i) { 737 str += String.fromCharCode(dataView.getUint8(i)); 738 } 739 console.log("tls on connect received:" + str); 740 }); 741 tlsTwoWay.on('connect', () => { 742 console.log("tls on connect"); 743 }); 744 tlsTwoWay.on('close', () => { 745 console.log("tls on close"); 746 }); 747 748 // 配置TLSSocket目的地址、证书等信息。 749 ipAddress.address = "192.168.xxx.xxx"; 750 ipAddress.port = 1234; 751 752 let tlsSecureOption: socket.TLSSecureOptions = {} as socket.TLSSecureOptions; 753 tlsSecureOption.key = "xxxx"; 754 tlsSecureOption.cert = "xxxx"; 755 tlsSecureOption.ca = ["xxxx"]; 756 tlsSecureOption.password = "xxxx"; 757 tlsSecureOption.protocols = [socket.Protocol.TLSv12]; 758 tlsSecureOption.useRemoteCipherPrefer = true; 759 tlsSecureOption.signatureAlgorithms = "rsa_pss_rsae_sha256:ECDSA+SHA256"; 760 tlsSecureOption.cipherSuite = "AES256-SHA256"; 761 762 let tlsTwoWayConnectOption: socket.TLSConnectOptions = {} as socket.TLSConnectOptions; 763 tlsSecureOption.key = "xxxx"; 764 tlsTwoWayConnectOption.address = ipAddress; 765 tlsTwoWayConnectOption.secureOptions = tlsSecureOption; 766 tlsTwoWayConnectOption.ALPNProtocols = ["spdy/1", "http/1.1"]; 767 768 // 建立TLSSocket连接 769 tlsTwoWay.connect(tlsTwoWayConnectOption, () => { 770 console.log("tls connect success"); 771 772 // 连接使用完毕后,主动关闭。取消相关事件的订阅。 773 tlsTwoWay.close((err: BusinessError) => { 774 if (err) { 775 console.log("tls close callback error = " + err); 776 } else { 777 console.log("tls close success"); 778 } 779 tlsTwoWay.off('message'); 780 tlsTwoWay.off('connect'); 781 tlsTwoWay.off('close'); 782 }); 783 }); 784 }); 785}); 786``` 787 788## 应用通过 TLS Socket Server 进行加密数据传输 789 790服务端 TLS Socket Server 流程: 791 7921. import 需要的 socket 模块。 793 7942. 启动服务,绑定 IP 和端口号,监听客户端连接,创建并初始化 TLS 会话,加载证书密钥并验证。 795 7963. 订阅 TLSSocketServer 的连接事件。 797 7984. 收到客户端连接,通过回调得到 TLSSocketConnection 对象。 799 8005. 订阅 TLSSocketConnection 相关的事件。 801 8026. 发送数据。 803 8047. TLSSocketConnection 连接使用完毕后,断开连接。 805 8068. 取消订阅 TLSSocketConnection 以及 TLSSocketServer 的相关事件。 807 808```ts 809import { socket } from '@kit.NetworkKit'; 810import { BusinessError } from '@kit.BasicServicesKit'; 811 812let tlsServer: socket.TLSSocketServer = socket.constructTLSSocketServerInstance(); 813 814let netAddress: socket.NetAddress = { 815 address: '192.168.xx.xxx', 816 port: 8080 817} 818 819let tlsSecureOptions: socket.TLSSecureOptions = { 820 key: "xxxx", 821 cert: "xxxx", 822 ca: ["xxxx"], 823 password: "xxxx", 824 protocols: socket.Protocol.TLSv12, 825 useRemoteCipherPrefer: true, 826 signatureAlgorithms: "rsa_pss_rsae_sha256:ECDSA+SHA256", 827 cipherSuite: "AES256-SHA256" 828} 829 830let tlsConnectOptions: socket.TLSConnectOptions = { 831 address: netAddress, 832 secureOptions: tlsSecureOptions, 833 ALPNProtocols: ["spdy/1", "http/1.1"] 834} 835 836tlsServer.listen(tlsConnectOptions).then(() => { 837 console.log("listen callback success"); 838}).catch((err: BusinessError) => { 839 console.log("failed" + err); 840}); 841 842class SocketInfo { 843 message: ArrayBuffer = new ArrayBuffer(1); 844 remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo; 845} 846let callback = (value: SocketInfo) => { 847 let messageView = ''; 848 for (let i: number = 0; i < value.message.byteLength; i++) { 849 let uint8Array = new Uint8Array(value.message) 850 let messages = uint8Array[i] 851 let message = String.fromCharCode(messages); 852 messageView += message; 853 } 854 console.log('on message message: ' + JSON.stringify(messageView)); 855 console.log('remoteInfo: ' + JSON.stringify(value.remoteInfo)); 856} 857tlsServer.on('connect', (client: socket.TLSSocketConnection) => { 858 client.on('message', callback); 859 860 // 发送数据 861 client.send('Hello, client!').then(() => { 862 console.log('send success'); 863 }).catch((err: BusinessError) => { 864 console.log('send fail'); 865 }); 866 867 // 断开连接 868 client.close().then(() => { 869 console.log('close success'); 870 }).catch((err: BusinessError) => { 871 console.log('close fail'); 872 }); 873 874 // 可以指定传入on中的callback取消一个订阅,也可以不指定callback清空所有订阅。 875 client.off('message', callback); 876 client.off('message'); 877}); 878 879// 取消订阅tlsServer的相关事件 880tlsServer.off('connect'); 881``` 882 883## 相关实例 884 885针对 Socket 连接开发,有以下相关实例可供参考: 886 887- [网络管理-Socket 连接(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Connectivity/Socket) 888