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 91 import socket from '@ohos.net.socket' 92 93 // 创建一个TCPSocket连接,返回一个TCPSocket对象。 94 let tcp = socket.constructTCPSocketInstance(); 95 96 // 订阅TCPSocket相关的订阅事件 97 tcp.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 }); 107 tcp.on('connect', () => { 108 console.log("on connect") 109 }); 110 tcp.on('close', () => { 111 console.log("on close") 112 }); 113 114 // 绑定本地IP地址和端口。 115 let bindAddress = { 116 address: '192.168.xx.xx', 117 port: 1234, // 绑定端口,如1234 118 family: 1 119 }; 120 tcp.bind(bindAddress, err => { 121 if (err) { 122 console.log('bind fail'); 123 return; 124 } 125 console.log('bind success'); 126 127 // 连接到指定的IP地址和端口。 128 let connectAddress = { 129 address: '192.168.xx.xx', 130 port: 5678, // 连接端口,如5678 131 family: 1 132 }; 133 tcp.connect({ 134 address: connectAddress, timeout: 6000 135 }, err => { 136 if (err) { 137 console.log('connect fail'); 138 return; 139 } 140 console.log('connect success'); 141 142 // 发送数据 143 tcp.send({ 144 data: 'Hello, server!' 145 }, err => { 146 if (err) { 147 console.log('send fail'); 148 return; 149 } 150 console.log('send success'); 151 }) 152 }); 153 }); 154 155 // 连接使用完毕后,主动关闭。取消相关事件的订阅。 156 setTimeout(() => { 157 tcp.close((err) => { 158 console.log('close socket.') 159 }); 160 tcp.off('message'); 161 tcp.off('connect'); 162 tcp.off('close'); 163 }, 30 * 1000); 164 ``` 165 166## 应用通过TLS Socket进行加密数据传输 167 168### 开发步骤 169 170客户端TLS Socket流程: 171 1721. import需要的socket模块。 173 1742. 绑定服务器IP和端口号。 175 1763. 双向认证上传客户端CA证书及数字证书;单向认证上传客户端CA证书。 177 1784. 创建一个TLSSocket连接,返回一个TLSSocket对象。 179 1805. (可选)订阅TLSSocket相关的订阅事件。 181 1826. 发送数据。 183 1847. TLSSocket连接使用完毕后,主动关闭。 185 186```js 187 import socket from '@ohos.net.socket' 188 189 // 创建一个(双向认证)TLS Socket连接,返回一个TLS Socket对象。 190 let tlsTwoWay = socket.constructTLSSocketInstance(); 191 192 // 订阅TLS Socket相关的订阅事件 193 tlsTwoWay.on('message', value => { 194 console.log("on message") 195 let buffer = value.message 196 let dataView = new DataView(buffer) 197 let str = "" 198 for (let i = 0; i < dataView.byteLength; ++i) { 199 str += String.fromCharCode(dataView.getUint8(i)) 200 } 201 console.log("on connect received:" + str) 202 }); 203 tlsTwoWay.on('connect', () => { 204 console.log("on connect") 205 }); 206 tlsTwoWay.on('close', () => { 207 console.log("on close") 208 }); 209 210 // 绑定本地IP地址和端口。 211 tlsTwoWay.bind({address: '192.168.xxx.xxx', port: xxxx, family: 1}, err => { 212 if (err) { 213 console.log('bind fail'); 214 return; 215 } 216 console.log('bind success'); 217 }); 218 219 // 设置通信过程中使用参数 220 let options = { 221 ALPNProtocols: ["spdy/1", "http/1.1"], 222 223 // 连接到指定的IP地址和端口。 224 address: { 225 address: "192.168.xx.xxx", 226 port: xxxx, // 端口 227 family: 1, 228 }, 229 230 // 设置用于通信过程中完成校验的参数。 231 secureOptions: { 232 key: "xxxx", // 密钥 233 cert: "xxxx", // 数字证书 234 ca: ["xxxx"], // CA证书 235 passwd: "xxxx", // 生成密钥时的密码 236 protocols: [socket.Protocol.TLSv12], // 通信协议 237 useRemoteCipherPrefer: true, // 是否优先使用对端密码套件 238 signatureAlgorithms: "rsa_pss_rsae_sha256:ECDSA+SHA256", // 签名算法 239 cipherSuite: "AES256-SHA256", // 密码套件 240 }, 241 }; 242 243 // 建立连接 244 tlsTwoWay.connect(options, (err, data) => { 245 console.error(err); 246 console.log(data); 247 }); 248 249 // 连接使用完毕后,主动关闭。取消相关事件的订阅。 250 tlsTwoWay.close((err) => { 251 if (err) { 252 console.log("close callback error = " + err); 253 } else { 254 console.log("close success"); 255 } 256 tlsTwoWay.off('message'); 257 tlsTwoWay.off('connect'); 258 tlsTwoWay.off('close'); 259 }); 260 261 // 创建一个(单向认证)TLS Socket连接,返回一个TLS Socket对象。 262 let tlsOneWay = socket.constructTLSSocketInstance(); // One way authentication 263 264 // 订阅TLS Socket相关的订阅事件 265 tlsTwoWay.on('message', value => { 266 console.log("on message") 267 let buffer = value.message 268 let dataView = new DataView(buffer) 269 let str = "" 270 for (let i = 0;i < dataView.byteLength; ++i) { 271 str += String.fromCharCode(dataView.getUint8(i)) 272 } 273 console.log("on connect received:" + str) 274 }); 275 tlsTwoWay.on('connect', () => { 276 console.log("on connect") 277 }); 278 tlsTwoWay.on('close', () => { 279 console.log("on close") 280 }); 281 282 // 绑定本地IP地址和端口。 283 tlsOneWay.bind({address: '192.168.xxx.xxx', port: xxxx, family: 1}, err => { 284 if (err) { 285 console.log('bind fail'); 286 return; 287 } 288 console.log('bind success'); 289 }); 290 291 // 设置通信过程中使用参数 292 let oneWayOptions = { 293 address: { 294 address: "192.168.xxx.xxx", 295 port: xxxx, 296 family: 1, 297 }, 298 secureOptions: { 299 ca: ["xxxx","xxxx"], // CA证书 300 cipherSuite: "AES256-SHA256", // 密码套件 301 }, 302 }; 303 304 // 建立连接 305 tlsOneWay.connect(oneWayOptions, (err, data) => { 306 console.error(err); 307 console.log(data); 308 }); 309 310 // 连接使用完毕后,主动关闭。取消相关事件的订阅。 311 tlsTwoWay.close((err) => { 312 if (err) { 313 console.log("close callback error = " + err); 314 } else { 315 console.log("close success"); 316 } 317 tlsTwoWay.off('message'); 318 tlsTwoWay.off('connect'); 319 tlsTwoWay.off('close'); 320 }); 321``` 322 323## 相关实例 324 325针对Socket连接开发,有以下相关实例可供参考: 326- [`Socket`:Socket 连接(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/OpenHarmony-3.2-Release/Network/Socket) 327- [使用UDP实现与服务端通信(ArkTS)(API9)](https://gitee.com/openharmony/codelabs/tree/master/NetworkManagement/UdpDemoOH) 328- [使用TCP实现与服务端通信(ArkTS)(API9)](https://gitee.com/openharmony/codelabs/tree/master/NetworkManagement/TcpSocketDemo) 329