1# Socket连接 2 3## 简介 4 5Socket连接主要是通过Socket进行数据传输,支持TCP/UDP/TLS协议。 6 7## 基本概念 8 9- Socket:套接字,就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。 10- TCP:传输控制协议(Transmission Control Protocol)。是一种面向连接的、可靠的、基于字节流的传输层通信协议。 11- UDP:用户数据报协议协议(User Datagram Protocol)。是一个简单的面向消息的传输层,不需要连接。 12- TLS:安全传输层协议(Transport Layer Security)。用于在两个通信应用程序之间提供保密性和数据完整性。 13 14## 场景介绍 15 16应用通过Socket进行数据传输,支持TCP/UDP/TLS协议。主要场景有: 17 18- 应用通过TCP/UDP Socket进行数据传输 19- 应用通过TLS Socket进行加密数据传输 20 21## 接口说明 22 23完整的JS API说明以及实例代码请参考:[Socket连接](../reference/apis/js-apis-socket.md)。 24 25Socket连接主要由socket模块提供。具体接口说明如下表。 26 27| 接口名 | 功能描述 | 28| -------- | -------- | 29| constructUDPSocketInstance() | 创建一个UDPSocket对象。 | 30| constructTCPSocketInstance() | 创建一个TCPSocket对象。 | 31| bind() | 绑定IP地址和端口。 | 32| send() | 发送数据。 | 33| close() | 关闭连接。 | 34| getState() | 获取Socket状态。 | 35| connect() | 连接到指定的IP地址和端口(仅TCP支持) | 36| getRemoteAddress() | 获取对端Socket地址(仅TCP支持,需要先调用connect方法) | 37| on(type: 'message') | 订阅Socket连接的接收消息事件。 | 38| off(type: 'message') | 取消订阅Socket连接的接收消息事件。 | 39| on(type: 'close') | 订阅Socket连接的关闭事件。 | 40| off(type: 'close') | 取消订阅Socket连接的关闭事件。 | 41| on(type: 'error') | 订阅Socket连接的Error事件。 | 42| off(type: 'error') | 取消订阅Socket连接的Error事件。 | 43| on(type: 'listening') | 订阅UDPSocket连接的数据包消息事件(仅UDP支持)。 | 44| off(type: 'listening') | 取消订阅UDPSocket连接的数据包消息事件(仅UDP支持)。 | 45| on(type: 'connect') | 订阅TCPSocket的连接事件(仅TCP支持)。 | 46| off(type: 'connect') | 取消订阅TCPSocket的连接事件(仅TCP支持)。 | 47 48TLS Socket连接主要由tls_socket模块提供。具体接口说明如下表。 49 50| 接口名 | 功能描述 | 51| -------- | -------- | 52| constructTLSSocketInstance() | 创建一个TLSSocket对象。 | 53| bind() | 绑定IP地址和端口号。 | 54| close(type: 'error') | 关闭连接。 | 55| connect() | 连接到指定的IP地址和端口。 | 56| getCertificate() | 返回表示本地证书的对象。 | 57| getCipherSuite() | 返回包含协商的密码套件信息的列表。 | 58| getProtocol() | 返回包含当前连接协商的SSL/TLS协议版本的字符串。 | 59| getRemoteAddress() | 获取TLSSocket连接的对端地址。 | 60| getRemoteCertificate() | 返回表示对等证书的对象。 | 61| getSignatureAlgorithms() | 在服务器和客户端之间共享的签名算法列表,按优先级降序排列。 | 62| getState() | 获取TLSSocket连接的状态。 | 63| off(type: 'close') | 取消订阅TLSSocket连接的关闭事件。 | 64| off(type: 'error') | 取消订阅TLSSocket连接的Error事件。 | 65| off(type: 'message') | 取消订阅TLSSocket连接的接收消息事件。 | 66| on(type: 'close') | 订阅TLSSocket连接的关闭事件。 | 67| on(type: 'error') | 订阅TLSSocket连接的Error事件。 | 68| on(type: 'message') | 订阅TLSSocket连接的接收消息事件。 | 69| send() | 发送数据。 | 70| setExtraOptions() | 设置TLSSocket连接的其他属性。 | 71 72## 应用TCP/UDP协议进行通信 73 74UDP与TCP流程大体类似,下面以TCP为例: 75 761. import需要的socket模块。 77 782. 创建一个TCPSocket连接,返回一个TCPSocket对象。 79 803. (可选)订阅TCPSocket相关的订阅事件。 81 824. 绑定IP地址和端口,端口可以指定或由系统随机分配。 83 845. 连接到指定的IP地址和端口。 85 866. 发送数据。 87 887. Socket连接使用完毕后,主动关闭。 89 90```js 91import socket from '@ohos.net.socket' 92 93// 创建一个TCPSocket连接,返回一个TCPSocket对象。 94let tcp = socket.constructTCPSocketInstance(); 95 96// 订阅TCPSocket相关的订阅事件 97tcp.on('message', value => { 98 console.log("on message") 99 let buffer = value.message 100 let dataView = new DataView(buffer) 101 let str = "" 102 for (let i = 0; i < dataView.byteLength; ++i) { 103 str += String.fromCharCode(dataView.getUint8(i)) 104 } 105 console.log("on connect received:" + str) 106}); 107tcp.on('connect', () => { 108 console.log("on connect") 109}); 110tcp.on('close', () => { 111 console.log("on close") 112}); 113 114// 绑定IP地址和端口。 115let bindAddress = { 116 address: '192.168.xx.xx', 117 port: 1234, // 绑定端口,如1234 118 family: 1 119}; 120tcp.bind(bindAddress, err => { 121 if (err) { 122 console.log('bind fail'); 123 return; 124 } 125 console.log('bind success'); 126 // 连接到指定的IP地址和端口。 127 let connectAddress = { 128 address: '192.168.xx.xx', 129 port: 5678, // 连接端口,如5678 130 family: 1 131 }; 132 tcp.connect({ 133 address: connectAddress, timeout: 6000 134 }, err => { 135 if (err) { 136 console.log('connect fail'); 137 return; 138 } 139 console.log('connect success'); 140 // 发送数据 141 tcp.send({ 142 data: 'Hello, server!' 143 }, err => { 144 if (err) { 145 console.log('send fail'); 146 return; 147 } 148 console.log('send success'); 149 }) 150 }); 151}); 152// 连接使用完毕后,主动关闭。取消相关事件的订阅。 153setTimeout(() => { 154 tcp.close((err) => { 155 console.log('close socket.') 156 }); 157 tcp.off('message'); 158 tcp.off('connect'); 159 tcp.off('close'); 160}, 30 * 1000); 161``` 162 163## 应用通过TLS Socket进行加密数据传输 164 165### 开发步骤 166 167客户端TLS Socket流程: 168 1691. import需要的socket模块。 170 1712. 绑定服务器IP和端口号。 172 1733. 双向认证上传客户端CA证书及数字证书;单向认证上传客户端CA证书。 174 1754. 创建一个TLSSocket连接,返回一个TLSSocket对象。 176 1775. (可选)订阅TLSSocket相关的订阅事件。 178 1796. 发送数据。 180 1817. TLSSocket连接使用完毕后,主动关闭。 182 183```js 184// 创建一个(双向认证)TLS Socket连接,返回一个TLS Socket对象。 185let tlsTwoWay = socket.constructTLSSocketInstance(); 186 187// 订阅TLS Socket相关的订阅事件 188tlsTwoWay.on('message', value => { 189 console.log("on message") 190 let buffer = value.message 191 let dataView = new DataView(buffer) 192 let str = "" 193 for (let i = 0; i < dataView.byteLength; ++i) { 194 str += String.fromCharCode(dataView.getUint8(i)) 195 } 196 console.log("on connect received:" + str) 197}); 198tlsTwoWay.on('connect', () => { 199 console.log("on connect") 200}); 201tlsTwoWay.on('close', () => { 202 console.log("on close") 203}); 204 205// 绑定本地IP地址和端口。 206tlsTwoWay.bind({ address: '192.168.xxx.xxx', port: xxxx, family: 1 }, err => { 207 if (err) { 208 console.log('bind fail'); 209 return; 210 } 211 console.log('bind success'); 212}); 213 214// 设置通信过程中使用参数 215let options = { 216 ALPNProtocols: ["spdy/1", "http/1.1"], 217 218 // 连接到指定的IP地址和端口。 219 address: { 220 address: "192.168.xx.xxx", 221 port: xxxx, // 端口 222 family: 1, 223 }, 224 225 // 设置用于通信过程中完成校验的参数。 226 secureOptions: { 227 key: "xxxx", // 密钥 228 cert: "xxxx", // 数字证书 229 ca: ["xxxx"], // CA证书 230 passwd: "xxxx", // 生成密钥时的密码 231 protocols: [socket.Protocol.TLSv12], // 通信协议 232 useRemoteCipherPrefer: true, // 是否优先使用对端密码套件 233 signatureAlgorithms: "rsa_pss_rsae_sha256:ECDSA+SHA256", // 签名算法 234 cipherSuite: "AES256-SHA256", // 密码套件 235 }, 236}; 237 238// 建立连接 239tlsTwoWay.connect(options, (err, data) => { 240 console.error(err); 241 console.log(data); 242}); 243 244// 连接使用完毕后,主动关闭。取消相关事件的订阅。 245tlsTwoWay.close((err) => { 246 if (err) { 247 console.log("close callback error = " + err); 248 } else { 249 console.log("close success"); 250 } 251 tlsTwoWay.off('message'); 252 tlsTwoWay.off('connect'); 253 tlsTwoWay.off('close'); 254}); 255 256// 创建一个(单向认证)TLS Socket连接,返回一个TLS Socket对象。 257let tlsOneWay = socket.constructTLSSocketInstance(); // One way authentication 258 259// 订阅TLS Socket相关的订阅事件 260tlsTwoWay.on('message', value => { 261 console.log("on message") 262 let buffer = value.message 263 let dataView = new DataView(buffer) 264 let str = "" 265 for (let i = 0; i < dataView.byteLength; ++i) { 266 str += String.fromCharCode(dataView.getUint8(i)) 267 } 268 console.log("on connect received:" + str) 269}); 270tlsTwoWay.on('connect', () => { 271 console.log("on connect") 272}); 273tlsTwoWay.on('close', () => { 274 console.log("on close") 275}); 276 277// 绑定本地IP地址和端口。 278tlsOneWay.bind({ address: '192.168.xxx.xxx', port: xxxx, family: 1 }, err => { 279 if (err) { 280 console.log('bind fail'); 281 return; 282 } 283 console.log('bind success'); 284}); 285 286// 设置通信过程中使用参数 287let oneWayOptions = { 288 address: { 289 address: "192.168.xxx.xxx", 290 port: xxxx, 291 family: 1, 292 }, 293 secureOptions: { 294 ca: ["xxxx", "xxxx"], // CA证书 295 cipherSuite: "AES256-SHA256", // 密码套件 296 }, 297}; 298 299// 建立连接 300tlsOneWay.connect(oneWayOptions, (err, data) => { 301 console.error(err); 302 console.log(data); 303}); 304 305// 连接使用完毕后,主动关闭。取消相关事件的订阅。 306tlsTwoWay.close((err) => { 307 if (err) { 308 console.log("close callback error = " + err); 309 } else { 310 console.log("close success"); 311 } 312 tlsTwoWay.off('message'); 313 tlsTwoWay.off('connect'); 314 tlsTwoWay.off('close'); 315}); 316``` 317 318