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```ts 354import { socket } from '@kit.NetworkKit'; 355 356// 创建一个LocalSocket连接,返回一个LocalSocket对象。 357let client: socket.LocalSocket = socket.constructLocalSocketInstance(); 358client.on('message', (value: socket.LocalSocketMessageInfo) => { 359 const uintArray = new Uint8Array(value.message) 360 let messageView = ''; 361 for (let i = 0; i < uintArray.length; i++) { 362 messageView += String.fromCharCode(uintArray[i]); 363 } 364 console.log('total receive: ' + JSON.stringify(value)); 365 console.log('message information: ' + messageView); 366}); 367client.on('connect', () => { 368 console.log("on connect"); 369}); 370client.on('close', () => { 371 console.log("on close"); 372}); 373 374// 传入指定的本地套接字路径,连接服务端。 375let sandboxPath: string = getContext(this).filesDir + '/testSocket' 376let localAddress : socket.LocalAddress = { 377 address: sandboxPath 378} 379let connectOpt: socket.LocalConnectOptions = { 380 address: localAddress, 381 timeout: 6000 382} 383let sendOpt: socket.LocalSendOptions = { 384 data: 'Hello world!' 385} 386client.connect(connectOpt).then(() => { 387 console.log('connect success') 388 client.send(sendOpt).then(() => { 389 console.log('send success') 390 }).catch((err: Object) => { 391 console.log('send failed: ' + JSON.stringify(err)) 392 }) 393}).catch((err: Object) => { 394 console.log('connect fail: ' + JSON.stringify(err)); 395}); 396 397// 当不需要再连接服务端,需要断开且取消事件的监听时 398client.off('message'); 399client.off('connect'); 400client.off('close'); 401client.close().then(() => { 402 console.log('close client success') 403}).catch((err: Object) => { 404 console.log('close client err: ' + JSON.stringify(err)) 405}) 406``` 407 408## 应用通过 Local Socket Server 进行数据传输 409 410服务端 LocalSocket Server 流程: 411 4121. import 需要的 socket 模块。 413 4142. 使用 constructLocalSocketServerInstance 接口,创建一个 LocalSocketServer 服务端对象。 415 4163. 启动服务,绑定本地套接字路径,创建出本地套接字文件,监听客户端的连接请求。 417 4184. 注册 LocalSocket 的客户端连接(connect)事件,以及一些其它事件(可选)。 419 4205. 在客户端连接上来时,通过连接事件的回调函数,获取连接会话对象。 421 4226. 给会话对象 LocalSocketConnection 注册消息(message)事件,以及一些其它事件(可选)。 423 4247. 通过会话对象主动向客户端发送消息。 425 4268. 结束与客户端的通信,主动断开与客户端的连接。 427 4289. 取消 LocalSocketConnection 和 LocalSocketServer 相关事件的订阅。 429 430```ts 431import { socket } from '@kit.NetworkKit'; 432 433// 创建一个LocalSocketServer连接,返回一个LocalSocketServer对象。 434let server: socket.LocalSocketServer = socket.constructLocalSocketServerInstance(); 435// 创建并绑定本地套接字文件testSocket,进行监听 436let sandboxPath: string = getContext(this).filesDir + '/testSocket' 437let listenAddr: socket.LocalAddress = { 438 address: sandboxPath 439} 440server.listen(listenAddr).then(() => { 441 console.log("listen success"); 442}).catch((err: Object) => { 443 console.log("listen fail: " + JSON.stringify(err)); 444}); 445 446// 订阅LocalSocketServer的connect事件 447server.on('connect', (connection: socket.LocalSocketConnection) => { 448 // 订阅LocalSocketConnection相关的事件 449 connection.on('error', (err: Object) => { 450 console.log("on error success"); 451 }); 452 connection.on('message', (value: socket.LocalSocketMessageInfo) => { 453 const uintArray = new Uint8Array(value.message); 454 let messageView = ''; 455 for (let i = 0; i < uintArray.length; i++) { 456 messageView += String.fromCharCode(uintArray[i]); 457 } 458 console.log('total: ' + JSON.stringify(value)); 459 console.log('message information: ' + messageView); 460 }); 461 462 connection.on('error', (err: Object) => { 463 console.log("err:" + JSON.stringify(err)); 464 }) 465 466 // 向客户端发送数据 467 let sendOpt : socket.LocalSendOptions = { 468 data: 'Hello world!' 469 }; 470 connection.send(sendOpt).then(() => { 471 console.log('send success'); 472 }).catch((err: Object) => { 473 console.log('send failed: ' + JSON.stringify(err)); 474 }) 475 476 // 关闭与客户端的连接 477 connection.close().then(() => { 478 console.log('close success'); 479 }).catch((err: Object) => { 480 console.log('close failed: ' + JSON.stringify(err)); 481 }); 482 483 // 取消LocalSocketConnection相关的事件订阅 484 connection.off('message'); 485 connection.off('error'); 486}); 487 488// 取消LocalSocketServer相关的事件订阅 489server.off('connect'); 490server.off('error'); 491``` 492 493## 应用通过 TLS Socket 进行加密数据传输 494 495客户端 TLS Socket 流程: 496 4971. import 需要的 socket 模块。 498 4992. 绑定服务器 IP 和端口号。 500 5013. 双向认证上传客户端 CA 证书及数字证书;单向认证上传客户端 CA 证书。 502 5034. 创建一个 TLSSocket 连接,返回一个 TLSSocket 对象。 504 5055. (可选)订阅 TLSSocket 相关的订阅事件。 506 5076. 发送数据。 508 5097. TLSSocket 连接使用完毕后,主动关闭。 510 511```ts 512import { socket } from '@kit.NetworkKit'; 513import { BusinessError } from '@kit.BasicServicesKit'; 514 515class SocketInfo { 516 message: ArrayBuffer = new ArrayBuffer(1); 517 remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo; 518} 519// 创建一个(双向认证)TLS Socket连接,返回一个TLS Socket对象。 520let tlsTwoWay: socket.TLSSocket = socket.constructTLSSocketInstance(); 521// 订阅TLS Socket相关的订阅事件 522tlsTwoWay.on('message', (value: SocketInfo) => { 523 console.log("on message"); 524 let buffer = value.message; 525 let dataView = new DataView(buffer); 526 let str = ""; 527 for (let i = 0; i < dataView.byteLength; ++i) { 528 str += String.fromCharCode(dataView.getUint8(i)); 529 } 530 console.log("on connect received:" + str); 531}); 532tlsTwoWay.on('connect', () => { 533 console.log("on connect"); 534}); 535tlsTwoWay.on('close', () => { 536 console.log("on close"); 537}); 538 539// 绑定本地IP地址和端口。 540let ipAddress : socket.NetAddress = {} as socket.NetAddress; 541ipAddress.address = "192.168.xxx.xxx"; 542ipAddress.port = 4512; 543tlsTwoWay.bind(ipAddress, (err: BusinessError) => { 544 if (err) { 545 console.log('bind fail'); 546 return; 547 } 548 console.log('bind success'); 549}); 550 551ipAddress.address = "192.168.xxx.xxx"; 552ipAddress.port = 1234; 553 554let tlsSecureOption : socket.TLSSecureOptions = {} as socket.TLSSecureOptions; 555tlsSecureOption.key = "xxxx"; 556tlsSecureOption.cert = "xxxx"; 557tlsSecureOption.ca = ["xxxx"]; 558tlsSecureOption.password = "xxxx"; 559tlsSecureOption.protocols = [socket.Protocol.TLSv12]; 560tlsSecureOption.useRemoteCipherPrefer = true; 561tlsSecureOption.signatureAlgorithms = "rsa_pss_rsae_sha256:ECDSA+SHA256"; 562tlsSecureOption.cipherSuite = "AES256-SHA256"; 563 564let tlsTwoWayConnectOption : socket.TLSConnectOptions = {} as socket.TLSConnectOptions; 565tlsSecureOption.key = "xxxx"; 566tlsTwoWayConnectOption.address = ipAddress; 567tlsTwoWayConnectOption.secureOptions = tlsSecureOption; 568tlsTwoWayConnectOption.ALPNProtocols = ["spdy/1", "http/1.1"]; 569 570// 建立连接 571tlsTwoWay.connect(tlsTwoWayConnectOption).then(() => { 572 console.log("connect successfully"); 573}).catch((err: BusinessError) => { 574 console.log("connect failed " + JSON.stringify(err)); 575}); 576 577// 连接使用完毕后,主动关闭。取消相关事件的订阅。 578tlsTwoWay.close((err: BusinessError) => { 579 if (err) { 580 console.log("close callback error = " + err); 581 } else { 582 console.log("close success"); 583 } 584 tlsTwoWay.off('message'); 585 tlsTwoWay.off('connect'); 586 tlsTwoWay.off('close'); 587}); 588 589// 创建一个(单向认证)TLS Socket连接,返回一个TLS Socket对象。 590let tlsOneWay: socket.TLSSocket = socket.constructTLSSocketInstance(); // One way authentication 591 592// 订阅TLS Socket相关的订阅事件 593tlsTwoWay.on('message', (value: SocketInfo) => { 594 console.log("on message"); 595 let buffer = value.message; 596 let dataView = new DataView(buffer); 597 let str = ""; 598 for (let i = 0; i < dataView.byteLength; ++i) { 599 str += String.fromCharCode(dataView.getUint8(i)); 600 } 601 console.log("on connect received:" + str); 602}); 603tlsTwoWay.on('connect', () => { 604 console.log("on connect"); 605}); 606tlsTwoWay.on('close', () => { 607 console.log("on close"); 608}); 609 610// 绑定本地IP地址和端口。 611ipAddress.address = "192.168.xxx.xxx"; 612ipAddress.port = 5445; 613tlsOneWay.bind(ipAddress, (err:BusinessError) => { 614 if (err) { 615 console.log('bind fail'); 616 return; 617 } 618 console.log('bind success'); 619}); 620 621ipAddress.address = "192.168.xxx.xxx"; 622ipAddress.port = 8789; 623let tlsOneWaySecureOption : socket.TLSSecureOptions = {} as socket.TLSSecureOptions; 624tlsOneWaySecureOption.ca = ["xxxx", "xxxx"]; 625tlsOneWaySecureOption.cipherSuite = "AES256-SHA256"; 626 627let tlsOneWayConnectOptions: socket.TLSConnectOptions = {} as socket.TLSConnectOptions; 628tlsOneWayConnectOptions.address = ipAddress; 629tlsOneWayConnectOptions.secureOptions = tlsOneWaySecureOption; 630 631// 建立连接 632tlsOneWay.connect(tlsOneWayConnectOptions).then(() => { 633 console.log("connect successfully"); 634}).catch((err: BusinessError) => { 635 console.log("connect failed " + JSON.stringify(err)); 636}); 637 638// 连接使用完毕后,主动关闭。取消相关事件的订阅。 639tlsTwoWay.close((err: BusinessError) => { 640 if (err) { 641 console.log("close callback error = " + err); 642 } else { 643 console.log("close success"); 644 } 645 tlsTwoWay.off('message'); 646 tlsTwoWay.off('connect'); 647 tlsTwoWay.off('close'); 648}); 649``` 650 651## 应用通过将 TCP Socket 升级为 TLS Socket 进行加密数据传输 652 653客户端 TCP Socket 升级为 TLS Socket 流程: 654 6551. import 需要的 socket 模块。 656 6572. 参考[应用 TCP/UDP 协议进行通信](#应用-tcpudp-协议进行通信),创建一个 TCPSocket 连接。 658 6593. 确保 TCPSocket 已连接后,使用该 TCPSocket 对象创建 TLSSocket 连接,返回一个 TLSSocket 对象。 660 6614. 双向认证上传客户端 CA 证书及数字证书;单向认证上传客户端 CA 证书。 662 6635. (可选)订阅 TLSSocket 相关的订阅事件。 664 6656. 发送数据。 666 6677. TLSSocket 连接使用完毕后,主动关闭。 668 669```ts 670import { socket } from '@kit.NetworkKit'; 671import { BusinessError } from '@kit.BasicServicesKit'; 672 673class SocketInfo { 674 message: ArrayBuffer = new ArrayBuffer(1); 675 remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo; 676} 677 678// 创建一个TCPSocket连接,返回一个TCPSocket对象。 679let tcp: socket.TCPSocket = socket.constructTCPSocketInstance(); 680tcp.on('message', (value: SocketInfo) => { 681 console.log("on message"); 682 let buffer = value.message; 683 let dataView = new DataView(buffer); 684 let str = ""; 685 for (let i = 0; i < dataView.byteLength; ++i) { 686 str += String.fromCharCode(dataView.getUint8(i)); 687 } 688 console.log("on connect received:" + str); 689}); 690tcp.on('connect', () => { 691 console.log("on connect"); 692}); 693 694// 绑定本地IP地址和端口。 695let ipAddress: socket.NetAddress = {} as socket.NetAddress; 696ipAddress.address = "192.168.xxx.xxx"; 697ipAddress.port = 1234; 698tcp.bind(ipAddress, (err: BusinessError) => { 699 if (err) { 700 console.log('bind fail'); 701 return; 702 } 703 console.log('bind success'); 704 705 // 连接到指定的IP地址和端口。 706 ipAddress.address = "192.168.xxx.xxx"; 707 ipAddress.port = 443; 708 709 let tcpConnect: socket.TCPConnectOptions = {} as socket.TCPConnectOptions; 710 tcpConnect.address = ipAddress; 711 tcpConnect.timeout = 6000; 712 713 tcp.connect(tcpConnect, (err: BusinessError) => { 714 if (err) { 715 console.log('connect fail'); 716 return; 717 } 718 console.log('connect success'); 719 720 // 确保TCPSocket已连接后,将其升级为TLSSocket连接。 721 let tlsTwoWay: socket.TLSSocket = socket.constructTLSSocketInstance(tcp); 722 // 订阅TLSSocket相关的订阅事件。 723 tlsTwoWay.on('message', (value: SocketInfo) => { 724 console.log("tls on message"); 725 let buffer = value.message; 726 let dataView = new DataView(buffer); 727 let str = ""; 728 for (let i = 0; i < dataView.byteLength; ++i) { 729 str += String.fromCharCode(dataView.getUint8(i)); 730 } 731 console.log("tls on connect received:" + str); 732 }); 733 tlsTwoWay.on('connect', () => { 734 console.log("tls on connect"); 735 }); 736 tlsTwoWay.on('close', () => { 737 console.log("tls on close"); 738 }); 739 740 // 配置TLSSocket目的地址、证书等信息。 741 ipAddress.address = "192.168.xxx.xxx"; 742 ipAddress.port = 1234; 743 744 let tlsSecureOption: socket.TLSSecureOptions = {} as socket.TLSSecureOptions; 745 tlsSecureOption.key = "xxxx"; 746 tlsSecureOption.cert = "xxxx"; 747 tlsSecureOption.ca = ["xxxx"]; 748 tlsSecureOption.password = "xxxx"; 749 tlsSecureOption.protocols = [socket.Protocol.TLSv12]; 750 tlsSecureOption.useRemoteCipherPrefer = true; 751 tlsSecureOption.signatureAlgorithms = "rsa_pss_rsae_sha256:ECDSA+SHA256"; 752 tlsSecureOption.cipherSuite = "AES256-SHA256"; 753 754 let tlsTwoWayConnectOption: socket.TLSConnectOptions = {} as socket.TLSConnectOptions; 755 tlsSecureOption.key = "xxxx"; 756 tlsTwoWayConnectOption.address = ipAddress; 757 tlsTwoWayConnectOption.secureOptions = tlsSecureOption; 758 tlsTwoWayConnectOption.ALPNProtocols = ["spdy/1", "http/1.1"]; 759 760 // 建立TLSSocket连接 761 tlsTwoWay.connect(tlsTwoWayConnectOption, () => { 762 console.log("tls connect success"); 763 764 // 连接使用完毕后,主动关闭。取消相关事件的订阅。 765 tlsTwoWay.close((err: BusinessError) => { 766 if (err) { 767 console.log("tls close callback error = " + err); 768 } else { 769 console.log("tls close success"); 770 } 771 tlsTwoWay.off('message'); 772 tlsTwoWay.off('connect'); 773 tlsTwoWay.off('close'); 774 }); 775 }); 776 }); 777}); 778``` 779 780## 应用通过 TLS Socket Server 进行加密数据传输 781 782服务端 TLS Socket Server 流程: 783 7841. import 需要的 socket 模块。 785 7862. 启动服务,绑定 IP 和端口号,监听客户端连接,创建并初始化 TLS 会话,加载证书密钥并验证。 787 7883. 订阅 TLSSocketServer 的连接事件。 789 7904. 收到客户端连接,通过回调得到 TLSSocketConnection 对象。 791 7925. 订阅 TLSSocketConnection 相关的事件。 793 7946. 发送数据。 795 7967. TLSSocketConnection 连接使用完毕后,断开连接。 797 7988. 取消订阅 TLSSocketConnection 以及 TLSSocketServer 的相关事件。 799 800```ts 801import { socket } from '@kit.NetworkKit'; 802import { BusinessError } from '@kit.BasicServicesKit'; 803 804let tlsServer: socket.TLSSocketServer = socket.constructTLSSocketServerInstance(); 805 806let netAddress: socket.NetAddress = { 807 address: '192.168.xx.xxx', 808 port: 8080 809} 810 811let tlsSecureOptions: socket.TLSSecureOptions = { 812 key: "xxxx", 813 cert: "xxxx", 814 ca: ["xxxx"], 815 password: "xxxx", 816 protocols: socket.Protocol.TLSv12, 817 useRemoteCipherPrefer: true, 818 signatureAlgorithms: "rsa_pss_rsae_sha256:ECDSA+SHA256", 819 cipherSuite: "AES256-SHA256" 820} 821 822let tlsConnectOptions: socket.TLSConnectOptions = { 823 address: netAddress, 824 secureOptions: tlsSecureOptions, 825 ALPNProtocols: ["spdy/1", "http/1.1"] 826} 827 828tlsServer.listen(tlsConnectOptions).then(() => { 829 console.log("listen callback success"); 830}).catch((err: BusinessError) => { 831 console.log("failed" + err); 832}); 833 834class SocketInfo { 835 message: ArrayBuffer = new ArrayBuffer(1); 836 remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo; 837} 838let callback = (value: SocketInfo) => { 839 let messageView = ''; 840 for (let i: number = 0; i < value.message.byteLength; i++) { 841 let uint8Array = new Uint8Array(value.message) 842 let messages = uint8Array[i] 843 let message = String.fromCharCode(messages); 844 messageView += message; 845 } 846 console.log('on message message: ' + JSON.stringify(messageView)); 847 console.log('remoteInfo: ' + JSON.stringify(value.remoteInfo)); 848} 849tlsServer.on('connect', (client: socket.TLSSocketConnection) => { 850 client.on('message', callback); 851 852 // 发送数据 853 client.send('Hello, client!').then(() => { 854 console.log('send success'); 855 }).catch((err: BusinessError) => { 856 console.log('send fail'); 857 }); 858 859 // 断开连接 860 client.close().then(() => { 861 console.log('close success'); 862 }).catch((err: BusinessError) => { 863 console.log('close fail'); 864 }); 865 866 // 可以指定传入on中的callback取消一个订阅,也可以不指定callback清空所有订阅。 867 client.off('message', callback); 868 client.off('message'); 869}); 870 871// 取消订阅tlsServer的相关事件 872tlsServer.off('connect'); 873``` 874 875## 相关实例 876 877针对 Socket 连接开发,有以下相关实例可供参考: 878 879- [网络管理-Socket 连接(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Connectivity/Socket) 880