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