1# 使用Socket访问网络 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 11Socket连接主要是通过Socket进行数据传输,支持TCP/UDP/Multicast/TLS协议。 12 13> **说明:** 14> 15> 应用退后台后,Socket可能会断开,当应用重新回到前台,发生通信失败时,需匹配错误码并重新创建新的TCP/UDP Socket。 16 17## 基本概念 18 19- Socket:套接字,就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。 20- TCP:传输控制协议(Transmission Control Protocol),是一种面向连接的、可靠的、基于字节流的传输层通信协议。 21- UDP:用户数据报协议(User Datagram Protocol),是一个简单的面向消息的传输层,不需要连接。 22- Multicast:多播,基于UDP的一种通信模式,用于实现组内所有设备之间广播形式的通信。 23- LocalSocket:本地套接字,IPC(Inter-Process Communication)进程间通信的一种,实现设备内进程之间相互通信,无需网络。 24- TLS:安全传输层协议(Transport Layer Security),用于在两个通信应用程序之间提供保密性和数据完整性。 25 26## 场景介绍 27 28应用通过Socket进行数据传输,支持TCP/UDP/Multicast/TLS协议。主要场景有: 29 30- 在TCP/UDP传输的客户端(UDP本身并没有客户端和服务器端的明确区分,此处描述UDP传输的客户端是指主动向服务器发送数据的一方),应用通过TCP/UDP Socket进行数据传输 31- 在TCP传输的服务器端,应用通过TCP Socket Server进行数据传输 32- 多播通信场景,应用通过Multicast Socket进行数据传输 33- 同一台主机上不同进程之间传输的客户端,应用通过Local Socket进行数据传输 34- 同一台主机上不同进程之间传输的服务器端,应用通过Local Socket Server进行数据传输 35- 数据加密传输时,客户端侧通过TLS Socket进行加密数据传输 36- 数据加密传输时,服务器侧通过TLS Socket Server进行加密数据传输 37 38>**说明:** 39> 40>在本文档的示例中,通过this.context来获取UIAbilityContext,其中this代表继承自UIAbility的UIAbility实例。如需在页面中使用UIAbilityContext提供的能力,请参见[获取UIAbility的上下文信息](../application-models/uiability-usage.md#获取uiability的上下文信息)。 41 42## 应用TCP/UDP协议进行通信 43 44UDP与TCP流程大体类似,下面以TCP为例: 45 461. 导入所需的socket模块。 47 48 ```ts 49 import { socket } from '@kit.NetworkKit'; 50 import { BusinessError } from '@kit.BasicServicesKit'; 51 ``` 52 532. 创建一个TCPSocket连接,返回一个TCPSocket对象。 54 55 ```ts 56 // 创建一个TCPSocket连接,返回一个TCPSocket对象。 57 let tcp: socket.TCPSocket = socket.constructTCPSocketInstance(); 58 ``` 59 603. (可选)订阅TCPSocket相关的订阅事件。 61 62 ```ts 63 class SocketInfo { 64 message: ArrayBuffer = new ArrayBuffer(1); 65 remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo; 66 } 67 68 tcp.on('message', (value: SocketInfo) => { 69 console.log("on message"); 70 let buffer = value.message; 71 let dataView = new DataView(buffer); 72 let str = ""; 73 for (let i = 0; i < dataView.byteLength; ++i) { 74 str += String.fromCharCode(dataView.getUint8(i)); 75 } 76 console.log("on connect received:" + str); 77 }); 78 tcp.on('connect', () => { 79 console.log("on connect"); 80 }); 81 tcp.on('close', () => { 82 console.log("on close"); 83 }); 84 ``` 85 864. 绑定IP地址和端口,端口可以指定或由系统随机分配,绑定成功后可以连接到指定的IP地址和端口,连接成功后可以发送数据。 87 88 ```ts 89 // 绑定本地IP地址和端口。 90 let ipAddress : socket.NetAddress = {} as socket.NetAddress; 91 ipAddress.address = "192.168.xxx.xxx"; 92 ipAddress.port = 1234; 93 tcp.bind(ipAddress, (err: BusinessError) => { 94 if (err) { 95 console.error('bind fail'); 96 return; 97 } 98 console.log('bind success'); 99 100 // bind成功后,连接到指定的IP地址和端口。 101 ipAddress.address = "192.168.xxx.xxx"; 102 ipAddress.port = 5678; 103 104 let tcpConnect : socket.TCPConnectOptions = {} as socket.TCPConnectOptions; 105 tcpConnect.address = ipAddress; 106 tcpConnect.timeout = 6000; 107 108 tcp.connect(tcpConnect).then(() => { 109 console.log('connect success'); 110 let tcpSendOptions: socket.TCPSendOptions = { 111 data: 'Hello, server!' 112 } 113 // 连接成功之后,发送数据。 114 tcp.send(tcpSendOptions).then(() => { 115 console.log('send success'); 116 }).catch((err: BusinessError) => { 117 console.error('send fail'); 118 }); 119 }).catch((err: BusinessError) => { 120 console.error('connect fail'); 121 }); 122 }); 123 ``` 124 1255. Socket连接使用完毕后,主动关闭。 126 127 ```ts 128 // 连接使用完毕后,主动关闭。取消相关事件的订阅。 129 setTimeout(() => { 130 tcp.close().then(() => { 131 console.log('close success'); 132 }).catch((err: BusinessError) => { 133 console.error('close fail'); 134 }); 135 tcp.off('message'); 136 tcp.off('connect'); 137 tcp.off('close'); 138 }, 30 * 1000); 139 ``` 140 141## 应用通过TCP Socket Server进行数据传输 142 143服务端TCP Socket流程: 144 1451. 导入所需的socket模块。 146 147 ```ts 148 import { socket } from '@kit.NetworkKit'; 149 import { BusinessError } from '@kit.BasicServicesKit'; 150 ``` 151 1522. 创建一个TCPSocketServer连接,返回一个TCPSocketServer对象。 153 154 ```ts 155 // 创建一个TCPSocketServer连接,返回一个TCPSocketServer对象。 156 let tcpServer: socket.TCPSocketServer = socket.constructTCPSocketServerInstance(); 157 ``` 158 1593. 绑定本地IP地址和端口,监听并接受与此套接字建立的客户端TCPSocket连接。 160 161 ```ts 162 // 绑定本地IP地址和端口,进行监听。 163 let ipAddress : socket.NetAddress = {} as socket.NetAddress; 164 ipAddress.address = "192.168.xxx.xxx"; 165 ipAddress.port = 4651; 166 tcpServer.listen(ipAddress).then(() => { 167 console.log('listen success'); 168 }).catch((err: BusinessError) => { 169 console.error('listen fail'); 170 }); 171 ``` 172 1734. 订阅TCPSocketServer的connect事件,用于监听客户端的连接状态。客户端与服务端建立连接后,会返回一个TCPSocketConnection对象,用于与客户端通信,通过该对象可以订阅与客户端的连接关闭、客户端数据接收事件,也可以进行向客户端发送数据、关闭与客户端的连接、取消订阅TCPSocketConnection相关事件的动作。 174 175 176 ```ts 177 class SocketInfo { 178 message: ArrayBuffer = new ArrayBuffer(1); 179 remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo; 180 } 181 // 订阅TCPSocketServer的connect事件,客户端与服务端建立连接后,返回一个TCPSocketConnection对象,用于与客户端通信。 182 tcpServer.on("connect", (client: socket.TCPSocketConnection) => { 183 // client即为建立连接后获取到的连接对象,可以通过该对象订阅TCPSocketConnection相关的事件。 184 client.on("close", () => { 185 console.log("on close success"); 186 }); 187 client.on("message", (value: SocketInfo) => { 188 let buffer = value.message; 189 let dataView = new DataView(buffer); 190 let str = ""; 191 for (let i = 0; i < dataView.byteLength; ++i) { 192 str += String.fromCharCode(dataView.getUint8(i)); 193 } 194 console.log("received message--:" + str); 195 console.log("received address--:" + value.remoteInfo.address); 196 console.log("received family--:" + value.remoteInfo.family); 197 console.log("received port--:" + value.remoteInfo.port); 198 console.log("received size--:" + value.remoteInfo.size); 199 }); 200 201 // 向客户端发送数据。 202 let tcpSendOptions : socket.TCPSendOptions = {} as socket.TCPSendOptions; 203 tcpSendOptions.data = 'Hello, client!'; 204 client.send(tcpSendOptions).then(() => { 205 console.log('send success'); 206 }).catch((err: Object) => { 207 console.error('send fail: ' + JSON.stringify(err)); 208 }); 209 210 // 关闭与客户端的连接。 211 client.close().then(() => { 212 console.log('close success'); 213 }).catch((err: BusinessError) => { 214 console.error('close fail'); 215 }); 216 217 // 取消TCPSocketConnection相关的事件订阅。 218 setTimeout(() => { 219 client.off("message"); 220 client.off("close"); 221 }, 10 * 1000); 222 }); 223 ``` 224 2255. 取消TCPSocketServer相关事件的订阅。 226 227 ```ts 228 // 取消TCPSocketServer相关的事件订阅。 229 setTimeout(() => { 230 tcpServer.off("connect"); 231 }, 30 * 1000); 232 ``` 233 234## 应用通过Multicast Socket进行数据传输 235 2361. 导入所需的socket模块。 237 238 ```ts 239 import { socket } from '@kit.NetworkKit'; 240 ``` 241 2422. 创建multicastSocket多播对象。 243 244 ```ts 245 // 创建Multicast对象。 246 let multicast: socket.MulticastSocket = socket.constructMulticastSocketInstance(); 247 ``` 248 2493. 指定多播IP与端口,加入多播组。 250 251 ```ts 252 let addr : socket.NetAddress = { 253 address: '239.255.0.1', 254 port: 32123, 255 family: 1 256 } 257 258 // 加入多播组。 259 multicast.addMembership(addr).then(() => { 260 console.log('addMembership success'); 261 }).catch((err: Object) => { 262 console.error('addMembership fail'); 263 }); 264 ``` 265 2664. 开启消息message监听。 267 268 ```ts 269 // 开启监听消息数据,将接收到的ArrayBuffer类型数据转换为String。 270 class SocketInfo { 271 message: ArrayBuffer = new ArrayBuffer(1); 272 remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo; 273 } 274 multicast.on('message', (data: SocketInfo) => { 275 console.info('接收的数据: ' + JSON.stringify(data)) 276 const uintArray = new Uint8Array(data.message) 277 let str = '' 278 for (let i = 0; i < uintArray.length; ++i) { 279 str += String.fromCharCode(uintArray[i]) 280 } 281 console.info(str) 282 }) 283 ``` 284 2855. 发送数据,数据以广播的形式传输,同一多播组中已经开启消息message监听的多播对象都会接收到数据。 286 287 ```ts 288 // 发送数据。 289 multicast.send({ data:'Hello12345', address: addr }).then(() => { 290 console.log('send success'); 291 }).catch((err: Object) => { 292 console.error('send fail, ' + JSON.stringify(err)); 293 }); 294 ``` 295 2966. 关闭message消息的监听。 297 298 ```ts 299 // 关闭消息的监听。 300 multicast.off('message') 301 ``` 302 3037. 退出多播组。 304 305 ```ts 306 // 退出多播组。 307 multicast.dropMembership(addr).then(() => { 308 console.log('drop membership success'); 309 }).catch((err: Object) => { 310 console.error('drop membership fail'); 311 }); 312 ``` 313 314## 应用通过LocalSocket进行数据传输 315 3161. 导入所需的socket模块。 317 318 ```ts 319 import { socket } from '@kit.NetworkKit'; 320 import { common } from '@kit.AbilityKit'; 321 ``` 322 3232. 使用constructLocalSocketInstance接口,创建一个LocalSocket客户端对象。 324 325 ```ts 326 // 创建一个LocalSocket连接,返回一个LocalSocket对象。 327 let client: socket.LocalSocket = socket.constructLocalSocketInstance(); 328 ``` 329 3303. 注册LocalSocket的消息(message)事件,以及一些其它事件(可选)。 331 332 ```ts 333 client.on('message', (value: socket.LocalSocketMessageInfo) => { 334 const uintArray = new Uint8Array(value.message) 335 let messageView = ''; 336 for (let i = 0; i < uintArray.length; i++) { 337 messageView += String.fromCharCode(uintArray[i]); 338 } 339 console.log('total receive: ' + JSON.stringify(value)); 340 console.log('message information: ' + messageView); 341 }); 342 client.on('connect', () => { 343 console.log("on connect"); 344 }); 345 client.on('close', () => { 346 console.log("on close"); 347 }); 348 ``` 349 3504. 连接到指定的本地套接字文件路径,连接成功之后可以发送数据。 351 352 <!--code_no_check--> 353 ```ts 354 // 传入指定的本地套接字路径,连接服务端。 355 let context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext; 356 let sandboxPath: string = context.filesDir + '/testSocket'; 357 let localAddress : socket.LocalAddress = { 358 address: sandboxPath 359 } 360 let connectOpt: socket.LocalConnectOptions = { 361 address: localAddress, 362 timeout: 6000 363 } 364 let sendOpt: socket.LocalSendOptions = { 365 data: 'Hello world!' 366 } 367 client.connect(connectOpt).then(() => { 368 console.log('connect success') 369 // 发送数据。 370 client.send(sendOpt).then(() => { 371 console.log('send success') 372 }).catch((err: Object) => { 373 console.error('send failed: ' + JSON.stringify(err)) 374 }) 375 }).catch((err: Object) => { 376 console.error('connect fail: ' + JSON.stringify(err)); 377 }); 378 ``` 379 3805. Socket连接使用完毕后,取消事件的注册,并关闭套接字。 381 382 ```ts 383 // 当不需要再连接服务端,需要断开且取消事件的监听时。 384 client.off('message'); 385 client.off('connect'); 386 client.off('close'); 387 client.close().then(() => { 388 console.log('close client success') 389 }).catch((err: Object) => { 390 console.error('close client err: ' + JSON.stringify(err)) 391 }) 392 ``` 393 394## 应用通过Local Socket Server进行数据传输 395 396服务端LocalSocket Server的主要流程包括: 397 3981. 导入所需的socket模块。 399 400 ```ts 401 import { socket } from '@kit.NetworkKit'; 402 import { common } from '@kit.AbilityKit'; 403 ``` 404 4052. 使用constructLocalSocketServerInstance接口,创建一个 LocalSocketServer 服务端对象。 406 407 ```ts 408 // 创建一个LocalSocketServer连接,返回一个LocalSocketServer对象。 409 let server: socket.LocalSocketServer = socket.constructLocalSocketServerInstance(); 410 ``` 411 4123. 启动服务,绑定本地套接字路径,创建出本地套接字文件,监听客户端的连接请求。 413 414 <!--code_no_check--> 415 ```ts 416 // 创建并绑定本地套接字文件testSocket,进行监听。 417 let context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext; 418 let sandboxPath: string = context.filesDir + '/testSocket'; 419 let listenAddr: socket.LocalAddress = { 420 address: sandboxPath 421 } 422 server.listen(listenAddr).then(() => { 423 console.log("listen success"); 424 }).catch((err: Object) => { 425 console.error("listen fail: " + JSON.stringify(err)); 426 }); 427 ``` 428 4294. 注册LocalSocket的客户端连接事件,以及一些其它事件(可选),在客户端连接成功时,可以获取到客户端连接会话对象LocalSocketConnection,通过该会话对象可以订阅客户端收到消息(message)事件,以及一些其它事件(可选),通过该会话对象也可发起主动向客户端发送数据,主动关闭与客户端的连接的动作,订阅事件不再需要时,可以取消LocalSocketConnection相关的事件订阅。 430 431 ```ts 432 // 订阅LocalSocketServer的connect事件。 433 server.on('connect', (connection: socket.LocalSocketConnection) => { 434 // 订阅LocalSocketConnection相关的事件。 435 connection.on('error', (err: Object) => { 436 console.log("on error success"); 437 }); 438 connection.on('message', (value: socket.LocalSocketMessageInfo) => { 439 const uintArray = new Uint8Array(value.message); 440 let messageView = ''; 441 for (let i = 0; i < uintArray.length; i++) { 442 messageView += String.fromCharCode(uintArray[i]); 443 } 444 console.log('total: ' + JSON.stringify(value)); 445 console.log('message information: ' + messageView); 446 }); 447 448 connection.on('error', (err: Object) => { 449 console.error("err:" + JSON.stringify(err)); 450 }) 451 452 // 向客户端发送数据。 453 let sendOpt : socket.LocalSendOptions = { 454 data: 'Hello world!' 455 }; 456 connection.send(sendOpt).then(() => { 457 console.log('send success'); 458 }).catch((err: Object) => { 459 console.log('send failed: ' + JSON.stringify(err)); 460 }) 461 462 // 关闭与客户端的连接。 463 connection.close().then(() => { 464 console.log('close success'); 465 }).catch((err: Object) => { 466 console.error('close failed: ' + JSON.stringify(err)); 467 }); 468 469 // 取消LocalSocketConnection相关的事件订阅。 470 connection.off('message'); 471 connection.off('error'); 472 }); 473 ``` 474 4755. 取消LocalSocketServer相关事件的订阅。 476 477 ```ts 478 // 取消LocalSocketServer相关的事件订阅。 479 server.off('connect'); 480 server.off('error'); 481 ``` 482 483## 应用通过TLS Socket进行加密数据传输 484 485客户端TLS Socket流程(双向认证)包括: 486 4871. 导入所需的socket模块。 488 489 ```ts 490 import { socket } from '@kit.NetworkKit'; 491 import { BusinessError } from '@kit.BasicServicesKit'; 492 ``` 493 4942. 创建一个双向认证TLSSocket连接,返回一个TLSSocket对象。 495 496 ```ts 497 // 创建一个(双向认证)TLS Socket连接,返回一个TLS Socket对象。 498 let tlsTwoWay: socket.TLSSocket = socket.constructTLSSocketInstance(); 499 ``` 500 5013. 绑定服务器IP地址和端口,确保bind成功后,再订阅TLS Socket相关的订阅事件。 502 503 ```ts 504 class SocketInfo { 505 message: ArrayBuffer = new ArrayBuffer(1); 506 remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo; 507 } 508 // 绑定本地IP地址和端口。 509 let ipAddress : socket.NetAddress = {} as socket.NetAddress; 510 ipAddress.address = "192.168.xxx.xxx"; 511 ipAddress.port = 4512; 512 tlsTwoWay.bind(ipAddress, (err: BusinessError) => { 513 if (err) { 514 console.error('bind fail'); 515 return; 516 } 517 console.log('bind success'); 518 // 确保bind成功后,再订阅TLS Socket相关的订阅事件 519 tlsTwoWay.on('message', (value: SocketInfo) => { 520 console.log("on message"); 521 let buffer = value.message; 522 let dataView = new DataView(buffer); 523 let str = ""; 524 for (let i = 0; i < dataView.byteLength; ++i) { 525 str += String.fromCharCode(dataView.getUint8(i)); 526 } 527 console.log("on connect received:" + str); 528 }); 529 tlsTwoWay.on('connect', () => { 530 console.log("on connect"); 531 }); 532 tlsTwoWay.on('close', () => { 533 console.log("on close"); 534 }); 535 }); 536 ``` 537 5384. 双向认证上传客户端CA证书及数字证书,并建立连接,连接建立成功后可以发送数据。 539 540 ```ts 541 ipAddress.address = "192.168.xxx.xxx"; 542 ipAddress.port = 1234; 543 544 let tlsSecureOption : socket.TLSSecureOptions = {} as socket.TLSSecureOptions; 545 tlsSecureOption.key = "xxxx"; 546 tlsSecureOption.cert = "xxxx"; 547 tlsSecureOption.ca = ["xxxx"]; 548 tlsSecureOption.password = "xxxx"; 549 tlsSecureOption.protocols = [socket.Protocol.TLSv12]; 550 tlsSecureOption.useRemoteCipherPrefer = true; 551 tlsSecureOption.signatureAlgorithms = "rsa_pss_rsae_sha256:ECDSA+SHA256"; 552 tlsSecureOption.cipherSuite = "AES256-SHA256"; 553 554 let tlsTwoWayConnectOption : socket.TLSConnectOptions = {} as socket.TLSConnectOptions; 555 tlsTwoWayConnectOption.address = ipAddress; 556 tlsTwoWayConnectOption.secureOptions = tlsSecureOption; 557 tlsTwoWayConnectOption.ALPNProtocols = ["spdy/1", "http/1.1"]; 558 559 // 建立连接,连接建立成功后,可以发送数据。 560 tlsTwoWay.connect(tlsTwoWayConnectOption).then(() => { 561 console.log("connect successfully"); 562 // 发送数据。 563 tlsTwoWay.send("xxxx").then(() => { 564 console.log("send successfully"); 565 }).catch((err: BusinessError) => { 566 console.error("send failed " + JSON.stringify(err)); 567 }); 568 }).catch((err: BusinessError) => { 569 console.error("connect failed " + JSON.stringify(err)); 570 }); 571 ``` 572 5735. TLSSocket连接使用完毕后,主动关闭。 574 575 ```ts 576 // 连接使用完毕后,主动关闭,并取消相关事件的订阅。 577 tlsTwoWay.close((err: BusinessError) => { 578 if (err) { 579 console.error("close callback error = " + err); 580 } else { 581 console.log("close success"); 582 } 583 tlsTwoWay.off('message'); 584 tlsTwoWay.off('connect'); 585 tlsTwoWay.off('close'); 586 }); 587 ``` 588 589客户端TLS Socket流程(单向认证)包括: 590 5911. 导入所需的socket模块。 592 593 ```ts 594 import { socket } from '@kit.NetworkKit'; 595 import { BusinessError } from '@kit.BasicServicesKit'; 596 ``` 597 5982. 创建一个单向认证TLSSocket连接,返回一个TLSSocket对象。 599 600 ```ts 601 // 创建一个(单向认证)TLS Socket连接,返回一个TLS Socket对象。 602 let tlsOneWay: socket.TLSSocket = socket.constructTLSSocketInstance(); // One way authentication 603 ``` 604 6053. 绑定服务器IP地址和端口,确保bind成功后,再订阅TLS Socket相关的订阅事件。。 606 607 ```ts 608 class SocketInfo { 609 message: ArrayBuffer = new ArrayBuffer(1); 610 remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo; 611 } 612 // 绑定本地IP地址和端口。 613 let ipAddress : socket.NetAddress = {} as socket.NetAddress; 614 ipAddress.address = "192.168.xxx.xxx"; 615 ipAddress.port = 5445; 616 tlsOneWay.bind(ipAddress, (err:BusinessError) => { 617 if (err) { 618 console.error('bind fail'); 619 return; 620 } 621 console.log('bind success'); 622 // 订阅TLS Socket相关的订阅事件 623 tlsOneWay.on('message', (value: SocketInfo) => { 624 console.log("on message"); 625 let buffer = value.message; 626 let dataView = new DataView(buffer); 627 let str = ""; 628 for (let i = 0; i < dataView.byteLength; ++i) { 629 str += String.fromCharCode(dataView.getUint8(i)); 630 } 631 console.log("on connect received:" + str); 632 }); 633 tlsOneWay.on('connect', () => { 634 console.log("on connect"); 635 }); 636 tlsOneWay.on('close', () => { 637 console.log("on close"); 638 }); 639 }); 640 ``` 641 6424. 单向认证上传客户端CA证书,并建立连接。 643 644 ```ts 645 ipAddress.address = "192.168.xxx.xxx"; 646 ipAddress.port = 8789; 647 let tlsOneWaySecureOption : socket.TLSSecureOptions = {} as socket.TLSSecureOptions; 648 tlsOneWaySecureOption.ca = ["xxxx", "xxxx"]; 649 tlsOneWaySecureOption.cipherSuite = "AES256-SHA256"; 650 651 let tlsOneWayConnectOptions: socket.TLSConnectOptions = {} as socket.TLSConnectOptions; 652 tlsOneWayConnectOptions.address = ipAddress; 653 tlsOneWayConnectOptions.secureOptions = tlsOneWaySecureOption; 654 655 // 建立连接,连接建立成功后,可以发送数据。 656 tlsOneWay.connect(tlsOneWayConnectOptions).then(() => { 657 console.log("connect successfully"); 658 // 发送数据。 659 tlsOneWay.send("xxxx").then(() => { 660 console.log("send successfully"); 661 }).catch((err: BusinessError) => { 662 console.error("send failed " + JSON.stringify(err)); 663 }); 664 }).catch((err: BusinessError) => { 665 console.error("connect failed " + JSON.stringify(err)); 666 }); 667 ``` 668 6695. TLSSocket连接使用完毕后,主动关闭。 670 671 ```ts 672 // 连接使用完毕后,主动关闭,并取消相关事件的订阅。 673 tlsOneWay.close((err: BusinessError) => { 674 if (err) { 675 console.error("close callback error = " + err); 676 } else { 677 console.log("close success"); 678 } 679 tlsOneWay.off('message'); 680 tlsOneWay.off('connect'); 681 tlsOneWay.off('close'); 682 }); 683 ``` 684 685## 应用通过将TCP Socket升级为TLS Socket进行加密数据传输 686 687客户端TCP Socket升级为TLS Socket流程,以TLS Socket双向认证为例: 688 6891. 导入所需的socket模块。 690 691 ```ts 692 import { socket } from '@kit.NetworkKit'; 693 import { BusinessError } from '@kit.BasicServicesKit'; 694 ``` 695 6962. 参考[应用 TCP/UDP 协议进行通信](#应用tcpudp协议进行通信),创建一个TCPSocket连接。 697 698 ```ts 699 // 创建一个TCPSocket连接,返回一个TCPSocket对象。 700 let tcp: socket.TCPSocket = socket.constructTCPSocketInstance(); 701 ``` 702 7033. (可选)订阅TCPSocket相关的订阅事件。 704 705 ```ts 706 class SocketInfo { 707 message: ArrayBuffer = new ArrayBuffer(1); 708 remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo; 709 } 710 711 tcp.on('message', (value: SocketInfo) => { 712 console.log("on message"); 713 let buffer = value.message; 714 let dataView = new DataView(buffer); 715 let str = ""; 716 for (let i = 0; i < dataView.byteLength; ++i) { 717 str += String.fromCharCode(dataView.getUint8(i)); 718 } 719 console.log("on connect received:" + str); 720 }); 721 tcp.on('connect', () => { 722 console.log("on connect"); 723 }); 724 ``` 725 7264. 绑定本地IP地址和端口,绑定成功后,连接到服务器端IP地址和端口,连接成功后使用该TCPSocket对象创建TLSSocket,配置双向认证上传客户端 CA 证书及数字证书,可以建立TLSSocket连接,连接使用完毕后,主动关闭并取消相关事件的订阅。。 727 728 ```ts 729 // 绑定本地IP地址和端口。 730 let ipAddress: socket.NetAddress = {} as socket.NetAddress; 731 ipAddress.address = "192.168.xxx.xxx"; 732 ipAddress.port = 1234; 733 tcp.bind(ipAddress, (err: BusinessError) => { 734 if (err) { 735 console.error('bind fail'); 736 return; 737 } 738 console.log('bind success'); 739 740 // 连接到服务器端指定的IP地址和端口。 741 ipAddress.address = "192.168.xxx.xxx"; 742 ipAddress.port = 443; 743 744 let tcpConnect: socket.TCPConnectOptions = {} as socket.TCPConnectOptions; 745 tcpConnect.address = ipAddress; 746 tcpConnect.timeout = 6000; 747 748 tcp.connect(tcpConnect, (err: BusinessError) => { 749 if (err) { 750 console.error('connect fail'); 751 return; 752 } 753 console.log('connect success'); 754 755 // 确保TCPSocket已连接后,将其升级为TLSSocket连接。 756 let tlsTwoWay: socket.TLSSocket = socket.constructTLSSocketInstance(tcp); 757 // 订阅TLSSocket相关的订阅事件。 758 tlsTwoWay.on('message', (value: SocketInfo) => { 759 console.log("tls on message"); 760 let buffer = value.message; 761 let dataView = new DataView(buffer); 762 let str = ""; 763 for (let i = 0; i < dataView.byteLength; ++i) { 764 str += String.fromCharCode(dataView.getUint8(i)); 765 } 766 console.log("tls on connect received:" + str); 767 }); 768 tlsTwoWay.on('connect', () => { 769 console.log("tls on connect"); 770 }); 771 tlsTwoWay.on('close', () => { 772 console.log("tls on close"); 773 }); 774 775 // 配置TLSSocket目的地址、证书等信息。 776 ipAddress.address = "192.168.xxx.xxx"; 777 ipAddress.port = 1234; 778 779 let tlsSecureOption: socket.TLSSecureOptions = {} as socket.TLSSecureOptions; 780 tlsSecureOption.key = "xxxx"; 781 tlsSecureOption.cert = "xxxx"; 782 tlsSecureOption.ca = ["xxxx"]; 783 tlsSecureOption.password = "xxxx"; 784 tlsSecureOption.protocols = [socket.Protocol.TLSv12]; 785 tlsSecureOption.useRemoteCipherPrefer = true; 786 tlsSecureOption.signatureAlgorithms = "rsa_pss_rsae_sha256:ECDSA+SHA256"; 787 tlsSecureOption.cipherSuite = "AES256-SHA256"; 788 789 let tlsTwoWayConnectOption: socket.TLSConnectOptions = {} as socket.TLSConnectOptions; 790 tlsSecureOption.key = "xxxx"; 791 tlsTwoWayConnectOption.address = ipAddress; 792 tlsTwoWayConnectOption.secureOptions = tlsSecureOption; 793 tlsTwoWayConnectOption.ALPNProtocols = ["spdy/1", "http/1.1"]; 794 795 // 建立TLSSocket连接。 796 tlsTwoWay.connect(tlsTwoWayConnectOption, () => { 797 console.log("tls connect success"); 798 799 // 连接使用完毕后,主动关闭。取消相关事件的订阅。 800 tlsTwoWay.close((err: BusinessError) => { 801 if (err) { 802 console.error("tls close callback error = " + err); 803 } else { 804 console.log("tls close success"); 805 } 806 tlsTwoWay.off('message'); 807 tlsTwoWay.off('connect'); 808 tlsTwoWay.off('close'); 809 }); 810 }); 811 }); 812 }); 813 ``` 814 815## 应用通过TLS Socket Server进行加密数据传输 816 817服务端TLS Socket Server流程: 818 8191. 导入所需的socket模块。 820 821 ```ts 822 import { socket } from '@kit.NetworkKit'; 823 import { BusinessError } from '@kit.BasicServicesKit'; 824 ``` 825 8262. 创建一个TLSSocketServer连接,返回一个TLSSocketServer对象。 827 828 ```ts 829 let tlsServer: socket.TLSSocketServer = socket.constructTLSSocketServerInstance(); 830 ``` 831 8323. 启动服务,绑定 IP 和端口号,监听客户端连接,创建并初始化TLS会话,加载证书密钥并验证。 833 834 ```ts 835 let netAddress: socket.NetAddress = { 836 address: '192.168.xx.xxx', 837 port: 8080 838 } 839 840 let tlsSecureOptions: socket.TLSSecureOptions = { 841 key: "xxxx", 842 cert: "xxxx", 843 ca: ["xxxx"], 844 password: "xxxx", 845 protocols: socket.Protocol.TLSv12, 846 useRemoteCipherPrefer: true, 847 signatureAlgorithms: "rsa_pss_rsae_sha256:ECDSA+SHA256", 848 cipherSuite: "AES256-SHA256" 849 } 850 851 let tlsConnectOptions: socket.TLSConnectOptions = { 852 address: netAddress, 853 secureOptions: tlsSecureOptions, 854 ALPNProtocols: ["spdy/1", "http/1.1"] 855 } 856 857 tlsServer.listen(tlsConnectOptions).then(() => { 858 console.log("listen callback success"); 859 }).catch((err: BusinessError) => { 860 console.error("failed" + err); 861 }); 862 ``` 863 8644. 订阅TLSSocketServer的连接事件,收到客户端连接,通过回调得到TLSSocketConnection对象,通过该对象可以实现订阅TLSSocketConnection相关的事件、向客户端发送数的动作,TLSSocketConnection连接使用完毕后,需要主动断开连接,进行取消订阅回调的动作。 865 866 ```ts 867 class SocketInfo { 868 message: ArrayBuffer = new ArrayBuffer(1); 869 remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo; 870 } 871 let callback = (value: SocketInfo) => { 872 let messageView = ''; 873 for (let i: number = 0; i < value.message.byteLength; i++) { 874 let uint8Array = new Uint8Array(value.message) 875 let messages = uint8Array[i] 876 let message = String.fromCharCode(messages); 877 messageView += message; 878 } 879 console.log('on message message: ' + JSON.stringify(messageView)); 880 console.log('remoteInfo: ' + JSON.stringify(value.remoteInfo)); 881 } 882 tlsServer.on('connect', (client: socket.TLSSocketConnection) => { 883 client.on('message', callback); 884 885 // 发送数据。 886 client.send('Hello, client!').then(() => { 887 console.log('send success'); 888 }).catch((err: BusinessError) => { 889 console.error('send fail'); 890 }); 891 892 // 断开连接。 893 client.close().then(() => { 894 console.log('close success'); 895 }).catch((err: BusinessError) => { 896 console.error('close fail'); 897 }); 898 899 // 可以指定传入on中的callback取消一个订阅,也可以不指定callback清空所有订阅。 900 client.off('message', callback); 901 client.off('message'); 902 }); 903 ``` 904 9055. 取消订阅TLSSocketServer的相关事件。 906 907 ```ts 908 // 取消订阅tlsServer的相关事件 909 tlsServer.off('connect'); 910 ``` 911 912## 相关实例 913 914针对Socket连接开发,有以下相关实例可供参考: 915 916- [网络管理-Socket连接(ArkTS)(API9)](https://gitcode.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Connectivity/Socket) 917 918- [Socket连接](https://gitcode.com/openharmony/applications_app_samples/tree/master/code/DocsSample/NetWork_Kit/NetWorkKit_Datatransmission/Socket) 919