鸿蒙Socket通信详解(附带实例)
Socket 连接主要是通过 Socket 进行数据传输,支持 TCP/UDP/Multicast/TLS 协议:
应用通过 Socket 进行数据传输,主要场景有:
TLS Socket 连接主要由 tls_socket 模块提供,具体接口说明如下表所示。
使用 TCP 进行通信的示例代码如下:

图 1 TCP通信
通过 TCP Socket Server 进行数据传输的示例代码如下:
Multicast Socket 进行数据传输的示例代码如下:
LocalSocket 进行数据传输的示例代码如下:
Local Socket Server 进行数据传输的示例代码如下:
客户端 TLS Socket 进行加密数据传输的示例代码如下:
客户端 TCP Socket 升级为 TLS Socket 进行加密数据传输的示例代码如下:
服务端 TLS Socket Server 进行加密数据传输的示例代码:
- Socket:套接字,就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象;
- TCP(Transmission Control Protocol):传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议;
- UDP(User Datagram Protocol):用户数据报协议,是一个简单的面向消息的传输层,不需要连接;
- Multicast:多播,基于UDP的一种通信模式,用于实现组内所有设备之间广播形式的通信;
- LocalSocket:本地套接字,IPC(Inter-Process Communication)进程间通信的一种,实现设备内进程之间的相互通信,无须网络;
- TLS(Transport Layer Security):安全传输层协议,用于在两个通信应用程序之间提供保密性和数据完整性。
应用通过 Socket 进行数据传输,主要场景有:
- 应用通过 TCP/UDP Socket 进行数据传输;
- 应用通过 TCP Socket Server 进行数据传输;
- 应用通过 Multicast Socket 进行数据传输;
- 应用通过 Local Socket 进行数据传输;
- 应用通过 Local Socket Server 进行数据传输;
- 应用通过 TLS Socket 进行加密数据传输;
- 应用通过 TLS Socket Server 进行加密数据传输。
Socket接口
Socket 连接主要由 socket 模块提供,具体接口说明如下表所示。| 接口名 | 说明 |
|---|---|
| constructUDPSocketInstance() | 创建一个 UDPSocket 对象 |
| constructTCPSocketInstance() | 创建一个 TCPSocket 对象 |
| constructTCPSocketServerInstance() | 创建一个 TCPSocketServer 对象 |
| constructMulticastSocketInstance() | 创建一个 MulticastSocket 对象 |
| constructLocalSocketInstance() | 创建一个 LocalSocket 对象 |
| constructLocalSocketServerInstance() | 创建一个 LocalSocketServer 对象 |
| listen() | 绑定、监听并启动服务,接收客户端的连接请求(仅 TCP/LocalSocket 支持) |
| bind() | 绑定 IP 地址和端口,或是绑定本地套接字路径 |
| send() | 发送数据 |
| close() | 关闭连接 |
| getState() | 获取 Socket 状态 |
| connect() | 连接到指定的 IP 地址和端口,或是连接到本地套接字(仅 TCP/LocalSocket 支持) |
| getRemoteAddress() | 获取对端 Socket 地址(仅 TCP 支持,需要先调用 connect 方法) |
| setExtraOptions() | 设置 Socket 连接的其他属性 |
| getExtraOptions() | 获取 Socket 连接的其他属性(仅 LocalSocket 支持) |
| addMembership() | 加入指定的多播组 IP 中(仅 Multicast 支持) |
| dropMembership() | 从指定的多播组 IP 中退出(仅 Multicast 支持) |
| setMulticastTTL() | 设置数据传输跳数 TTL(仅 Multicast 支持) |
| getMulticastTTL() | 获取数据传输跳数 TTL(仅 Multicast 支持) |
| setLoopbackMode() | 设置回环模式,允许主机在本地循环接收自己发送的多播数据包(仅 Multicast 支持) |
| getLoopbackMode() | 获取回环模式开启或关闭的状态(仅 Multicast 支持) |
| on(type: 'message') | 订阅 Socket 连接的接收消息事件 |
| off(type: 'message') | 取消订阅 Socket 连接的接收消息事件 |
| on(type: 'close') | 订阅 Socket 连接的关闭事件 |
| off(type: 'close') | 取消订阅 Socket 连接的关闭事件 |
| on(type: 'error') | 订阅 Socket 连接的 Error 事件 |
| off(type: 'error') | 取消订阅 Socket 连接的 Error 事件 |
| on(type: 'listening') | 订阅 UDPSocket 连接的数据包消息事件(仅 UDP 支持) |
| off(type: 'listening') | 取消订阅 UDPSocket 连接的数据包消息事件(仅 UDP 支持) |
| on(type: 'connect') | 订阅 Socket 的连接事件(仅 TCP/LocalSocket 支持) |
| off(type: 'connect') | 取消订阅 Socket 的连接事件(仅 TCP/LocalSocket 支持) |
TLS Socket 连接主要由 tls_socket 模块提供,具体接口说明如下表所示。
| 接口名 | 功能说明 |
|---|---|
| constructTLSSocketInstance() | 创建一个 TLS Socket 对象 |
| bind() | 绑定 IP 地址和端口号 |
| close(type: 'error') | 关闭连接 |
| connect() | 连接到指定的 IP 地址和端口 |
| _getCertificate() | 返回表示本地证书的对象 |
| _getCipherSuite() | 返回包含协商的密码套件信息的列表 |
| _getProtocol() | 返回包含当前连接协商的 SSL/TLS 协议版本的字符串 |
| _getRemoteAddress() | 获取 TLS Socket 连接的对端地址 |
| _getRemoteCertificate() | 返回表示对等证书的对象 |
| _getSignatureAlgorithms() | 在服务器和客户端之间共享的签名算法列表,按优先级降序排列 |
| getState() | 获取 TLS Socket 连接的状态 |
| off(type: 'close') | 取消订阅 TLS Socket 连接的关闭事件 |
| off(type: 'error') | 取消订阅 TLS Socket 连接的 Error 事件 |
| off(type: 'message') | 取消订阅 TLS Socket 连接的接收消息事件 |
| on(type: 'close') | 订阅 TLS Socket 连接的关闭事件 |
| on(type: 'error') | 订阅 TLSSocket 连接的 Error 事件 |
| on(type: 'message') | 订阅 TLS Socket 连接的接收消息事件 |
| send() | 发送数据 |
| setExtraOptions() | 设置 TLS Socket 连接的其他属性 |
TCP/UDP协议进行通信
UDP 与 TCP 流程大体类似,下面以 TCP 为例,说明通信步骤:- 导入需要的 socket 模块;
- 创建一个 TCPSocket 连接,返回一个 TCPSocket 对象;
- 订阅 TCPSocket 相关的订阅事件;
- 绑定 IP 地址和端口,端口可以指定或由系统随机分配;
- 连接到指定的 IP 地址和端口;
- 发送数据;
- Socket 连接使用完毕后,主动关闭。
使用 TCP 进行通信的示例代码如下:
// ...
class SocketInfo {
message: ArrayBuffer = new ArrayBuffer(1);
remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo;
}
// 创建一个 TCPSocket 连接,返回一个 TCPSocket 对象
let tcp: socket.TCPSocket = socket.constructTCPSocketInstance();
let str:string=""
// 监听接收消息事件
tcp.on('message', (value: SocketInfo) => {
console.log("监听 接收消息");
str += value.message+"\n";
console.log("连接,接收:" + str);
});
// 监听连接事件
tcp.on('connect', () => {
console.log("监听 连接 事件");
});
// 监听关闭事件
tcp.on('close', () => {
console.log("监听 关闭 事件");
});
// 绑定本地 IP 地址和端口
let ipAddress : socket.NetAddress = {} as socket.NetAddress;
ipAddress.address = "192.168.xxx.xxx";
ipAddress.port = 1234;
@Entry
@Component
struct Demo0401{
@State msg:string=""
build() {
Column() {
Button("连接 TCP ").width("90%").height(50).margin(10).
onClick(()=>{
// 开启绑定并连接到服务器
tcp.bind(ipAddress, (err: BusinessError) => {
if (err) {
console.log('绑定失败');
return;
}
console.log('绑定成功');
// 连接到指定的 IP 地址和端口
ipAddress.address = "192.168.xxx.xxx";
ipAddress.port = 5678;
let tcpConnect : socket.TCPConnectionOptions = {} as socket.TCPConnectionOptions;
tcpConnect.address = ipAddress;
tcpConnect.timeout = 6000;
tcp.connect(tcpConnect).then(() => {
console.log('连接成功');
let tcpSendOptions: socket.TCPSendOptions = {
data: '服务器,我是不是连接成功啦!'
}
tcp.send(tcpSendOptions).then(() => {
console.log('发送成功');
}).catch((err: BusinessError) => {
console.log('发送失败');
});
}).catch((err: BusinessError) => {
console.log('连接失败');
});
});
// 连接使用完毕后,主动关闭,并取消相关事件的订阅
setTimeout(() => {
tcp.close().then(() => {
console.log('关闭成功');
}).catch((err: BusinessError) => {
console.log('关闭失败');
});
tcp.off('message');
tcp.off('connect');
tcp.off('close');
}, 30 * 1000);
})
Row() {
TextInput({text:this.msg}).width("60%").height(50).margin(10)
Button("发送消息").width("40%").height(50).
onClick(()=>{
tcp.send({data:this.msg})
})
}.margin(10)
Button("关闭连接").width("90%").height(50).margin(10)
.onClick(()=>{
tcp.close()
})
}.width("100%")
}
}
运行效果如下图所示:
图 1 TCP通信
TCP Socket Server进行数据传输
服务端 TCP Socket Server 进行数据传输的步骤如下:- 导入需要的 socket 模块;
- 创建一个 TCPSocketServer 连接,返回一个 TCPSocketServer 对象;
- 绑定本地 IP 地址和端口,监听并接收与此套接字建立的客户端 TCPSocket 连接;
- 订阅 TCPSocketServer 的 connect 事件,用于监听客户端的连接状态;
- 客户端与服务端建立连接后,返回一个 TCPSocketConnection 对象,用于与客户端通信;
- 订阅 TCPSocketConnection 相关的事件,通过 TCPSocketConnection 向客户端发送数据;
- 主动关闭与客户端的连接;
- 取消 TCPSocketConnection 和 TCPSocketServer 相关事件的订阅。
通过 TCP Socket Server 进行数据传输的示例代码如下:
import { socket } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
// 创建一个 TCPSocketServer 连接,返回一个 TCPSocketServer 对象
let tcpServer: socket.TCPSocketServer = socket.constructTCPSocketServerInstance();
// 绑定本地 IP 地址和端口,进行监听
let ipAddress : socket.NetAddress = {} as socket.NetAddress;
ipAddress.address = "192.168.xxx.xxx";
ipAddress.port = 4651;
let str:string=""
// 服务端监听
tcpServer.listen(ipAddress).then(() => {
console.log('开启监听成功');
}).catch((err: BusinessError) => {
console.log('监听失败');
});
// 封装 Socket 信息类
class SocketInfo {
message: ArrayBuffer = new ArrayBuffer(1);
remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo;
}
// 订阅 TCPSocketServer 的 connect 事件
tcpServer.on("connect", (client: socket.TCPSocketConnection) => {
// 订阅 TCPSocketConnection 事件
client.on("close", () => {
console.log("监听 关闭 成功");
});
// 订阅消息接收事件
client.on("message", (value: SocketInfo) => {
str += value.message;
console.log("接收消息---:" + str);
console.log("远程地址---:" + value.remoteInfo.address);
});
// 向客户端发送数据
let tcpSendOptions : socket.TCPSendOptions = {} as socket.TCPSendOptions;
tcpSendOptions.data = 'Hello, client!';
client.send(tcpSendOptions).then(() => {
console.log('发送成功');
}).catch((err: Object) => {
console.error('发送失败: ' + JSON.stringify(err));
});
// 关闭与客户端的连接
client.close().then(() => {
console.log('关闭成功');
}).catch((err: BusinessError) => {
console.log('关闭 失败');
});
// 取消 TCPSocketConnection 相关的事件订阅
setTimeout(() => {
client.off("message");
client.off("close"),
10 * 1000);
});
// 取消 TCPSocketServer 相关的事件订阅
setTimeout(() => { tcpServer.off("connect") }, 30 * 1000);
});
Multicast Socket进行数据传输
Multicast Socket 进行数据传输的步骤如下:- 导入需要的 socket 模块;
- 创建 multicastSocket 多播对象;
- 指定多播 IP 地址与端口,加入多播组;
- 开启 message 监听;
- 发送数据,数据以广播的形式传输,同一多播组中已经开启 message 监听的多播对象都会接收到数据;
- 关闭 message 的监听;
- 退出多播组。
Multicast Socket 进行数据传输的示例代码如下:
import { socket } from '@kit.NetworkKit';
// 创建 Multicast 对象
let multicast: socket.MulticastSocket = socket.constructMulticastSocketInstance();
// 准备地址
let addr : socket.NetAddress = {
address: '239.255.0.1',
port: 32123,
family: 1
}
// 加入多播组
multicast.addMembership(addr).then(() => {
console.log('addMembership success');
}).catch((err: Object) => {
console.log('addMembership fail');
});
// 定义 Socket 信息类,用于接收数据
class SocketInfo {
message: ArrayBuffer = new ArrayBuffer(1);
remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo;
}
// 开启监听消息数据,将接收到的 ArrayBuffer 类型数据转换为 String
multicast.on('message', (data: SocketInfo) => {
console.info('接收的数据:' + JSON.stringify(data));
const uintArray = new Uint8Array(data.message);
let str = '';
for (let i = 0; i < uintArray.length; ++i) {
str += String.fromCharCode(uintArray[i]);
}
console.info(str);
})
// 发送数据
multicast.send({ data:'Hello12345', address: addr }).then(() => {
console.log('send success');
}).catch((err: Object) => {
console.log('send fail, ' + JSON.stringify(err));
});
// 关闭消息的监听
multicast.off('message');
// 退出多播组
multicast.dropMembership(addr).then(() => {
console.log('drop membership success');
}).catch((err: Object) => {
console.log('drop membership fail');
});
LocalSocket进行数据传输
LocalSocket 进行数据传输的步骤如下:- 导入需要的 socket 模块;
- 使用 constructLocalSocketInstance 接口,创建一个 LocalSocket 客户端对象;
- 注册 LocalSocket 的消息(message)事件,以及一些其他事件(可选);
- 连接到指定的本地套接字文件路径;
- 发送数据;
- Socket 连接使用完毕后,取消事件的注册,并关闭套接字。
LocalSocket 进行数据传输的示例代码如下:
import { socket } from '@kit.NetworkKit';
// 创建一个 LocalSocket 连接,返回一个 LocalSocket 对象
let client: socket.LocalSocket = socket.constructLocalSocketInstance();
// 监听接收消息事件
client.on('message', (value: socket.LocalSocketMessageInfo) => {
const uintArray = new Uint8Array(value.message)
let messageView = '';
for (let i = 0; i < uintArray.length; i++) {
messageView += String.fromCharCode(uintArray[i]);
}
console.log('总接收:' + JSON.stringify(value));
console.log('消息:' + messageView);
});
// 监听连接事件
client.on('connect', () => {
console.log("连接");
});
// 监听关闭事件
client.on('close', () => {
console.log("关闭");
});
// 传入指定的本地套接字路径,连接服务端
let sandboxPath: string = getContext(this).filesDir + '/testSocket'
let localAddress : socket.LocalAddress = {
address: sandboxPath
}
let connectOpt: socket.LocalConnectOptions = {
address: localAddress,
timeout: 6000
}
// 设置发送的消息内容
let sendOpt: socket.LocalSendOptions = {
data: 'Hello world!'
}
// 连接
client.connect(connectOpt).then(() => {
console.log('连接成功')
client.send(sendOpt).then(() => {
console.log('发送成功')
}).catch((err: Object) => {
console.log('发送失败:' + JSON.stringify(err))
}).catch((err: Object) => {
console.log('连接失败:' + JSON.stringify(err));
});
});
// 当不再需要连接服务端时,则断开且取消事件的监听
client.off('message');
client.off('connect');
client.off('close');
client.close().then(() => {
console.log('关闭成功')
}).catch((err: Object) => {
console.log('关闭错误:' + JSON.stringify(err))
})
Local Socket Server进行数据传输
服务端 Local Socket Server 进行数据传输的步骤如下:- 导入需要的 socket 模块;
- 使用 constructLocalSocketServerInstance 接口,创建一个 LocalSocketServer 服务端对象;
- 启动服务,绑定本地套接字路径,创建出本地套接字文件,监听客户端的连接请求;
- 注册 LocalSocket 的客户端连接(connect)事件,以及一些其他事件(可选);
- 当客户端连接上来时,通过连接事件的回调函数获取连接会话对象;
- 给会话对象 LocalSocketConnection 注册消息(message)事件,以及一些其他事件(可选)。
- 通过会话对象主动向客户端发送消息;
- 结束与客户端的通信,主动断开与客户端的连接;
- 取消 LocalSocketConnection 和 LocalSocketServer 相关事件的订阅。
Local Socket Server 进行数据传输的示例代码如下:
import { socket } from '@kit.NetworkKit';
// 创建一个 LocalSocketServer 连接,返回一个 LocalSocketServer 对象
let server: socket.LocalSocketServer = socket.constructLocalSocketServerInstance();
// 创建并绑定本地套接字文件 testSocket,进行监听
let sandboxPath: string = getContext(this).filesDir + '/testSocket'
let listenAddr: socket.LocalAddress = {
address: sandboxPath
}
// 监听
server.listen(listenAddr).then(() => {
console.log("listen success");
}).catch((err: Object) => {
console.log("listen fail: " + JSON.stringify(err));
});
// 订阅 LocalSocketServer 的 connect 事件
server.on('connect', (connection: socket.LocalSocketConnection) => {
// 订阅 LocalSocketConnection 相关的事件
connection.on('error', (err: Object) => {
console.log("on error success");
});
// 监听接收消息事件
connection.on('message', (value: socket.LocalSocketMessageInfo) => {
const uintArray = new Uint8Array(value.message);
let messageView = '';
for (let i = 0; i < uintArray.length; i++) {
messageView += String.fromCharCode(uintArray[i]);
}
console.log('total: ' + JSON.stringify(value));
console.log('message information: ' + messageView);
});
// 监听错误事件
connection.on('error', (err: Object) => {
console.log("err:" + JSON.stringify(err))
});
// 向客户端发送数据
let sendOpt: socket.LocalSendOptions = {
data: 'Hello world!'
};
// 发送消息
connection.send(sendOpt).then(() => {
console.log('send success');
}).catch((err: Object) => {
console.log('send failed: ' + JSON.stringify(err));
});
// 关闭与客户端的连接
connection.close().then(() => {
console.log('close success');
}).catch((err: Object) => {
console.log('close failed: ' + JSON.stringify(err));
});
// 取消 LocalSocketConnection 相关的事件订阅
connection.off('message');
connection.off('error');
});
TLS Socket进行加密数据传输
客户端 TLS Socket 进行加密数据传输的步骤如下:- 导入需要的 socket 模块;
- 绑定服务器 IP 地址和端口号;
- 双向认证则上传客户端 CA 证书及数字证书,单向认证则上传客户端 CA证书;
- 创建一个 TLSSocket 连接,返回一个 TLSSocket 对象;
- (可选)订阅 TLSSocket 相关的订阅事件;
- 发送数据;
- TLSSocket 连接使用完毕后,主动关闭。
客户端 TLS Socket 进行加密数据传输的示例代码如下:
import { socket } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
class SocketInfo {
message: ArrayBuffer = new ArrayBuffer(1);
remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo;
}
// 创建一个(双向认证)TLSSocket 连接,返回一个 TLSSocket 对象
let tlsTwoWay: socket.TLSSocket = socket.constructTLSSocketInstance();
// 订阅 TLSSocket 相关的订阅事件
tlsTwoWay.on('message', (value: SocketInfo) => {
console.log("订阅消息");
let buffer = value.message;
let dataView = new DataView(buffer);
let str = "";
for (let i = 0; i < dataView.byteLength; ++i) {
str += String.fromCharCode(dataView.getUint8(i));
}
console.log("接收消息:" + str);
});
// 监听连接
tlsTwoWay.on('connect', () => {
console.log("连接");
});
// 监听关闭
tlsTwoWay.on('close', () => {
console.log("关闭");
});
// 绑定本地 IP 地址和端口
let ipAddress : socket.NetAddress = {} as socket.NetAddress;
ipAddress.address = "192.168.xxx.xxx";
ipAddress.port = 4512;
// 绑定
tlsTwoWay.bind(ipAddress, (err: BusinessError) => {
if (err) {
console.log('绑定失败');
return;
}
console.log('绑定成功');
});
// ipAddress.address = "192.168.xxx.xxx";
ipAddress.port = 1234;
let tlsSecureOption : socket.TLSSecureOptions = {} as socket.TLSSecureOptions;
tlsSecureOption.key = "xxxx";
tlsSecureOption.cert = "xxxx";
tlsSecureOption.ca = ["xxxx"];
tlsSecureOption.password = "xxxx";
tlsSecureOption.protocols = [socket.Protocol.TLSv12];
tlsSecureOption.useRemoteCipherPrefer = true;
tlsSecureOption.signatureAlgorithms = "rsa_pss_rsae_sha256:ECDSA+SHA256";
tlsSecureOption.cipherSuite = "AES256-SHA256";
let tlsTwoWayConnectionOption : socket.TLSConnectionOptions = {} as socket.TLSConnectionOptions;
tlsSecureOption.key = "xxxx";
tlsTwoWayConnectionOption.address = ipAddress;
tlsTwoWayConnectionOption.secureOptions = tlsSecureOption;
tlsTwoWayConnectionOption.ALPNProtocols = ["spdy/1", "http/1.1"];
// 建立连接
tlsTwoWay.connect(tlsTwoWayConnectionOption).then(() => {
console.log("connect successfully");
}).catch((err: BusinessError) => {
console.log("connect failed " + JSON.stringify(err));
});
// 连接使用完毕后,主动关闭并取消相关事件的订阅
tlsTwoWay.close((err: BusinessError) => {
if (err) {
console.log("close callback error = " + err);
} else {
console.log("close success");
}
tlsTwoWay.off('message');
tlsTwoWay.off('connect');
tlsTwoWay.off('close');
});
// 创建一个(单向认证)TLS Socket 连接,返回一个 TLS Socket 对象
let tlsOneWay: socket.TLSSocket = socket.constructTLSSocketInstance();
// One way authentication
// 订阅 TLS Socket 相关的订阅事件
tlsTwoWay.on('message', (value: SocketInfo) => {
console.log("订阅消息 2");
let buffer = value.message;
let dataView = new DataView(buffer);
let str = "";
for (let i = 0; i < dataView.byteLength; ++i) {
str += String.fromCharCode(dataView.getUint8(i));
}
console.log("接收消息 2:" + str);
});
tlsTwoWay.on('connect', () => {
console.log("连接 2");
});
tlsTwoWay.on('close', () => {
console.log("关闭 2");
});
// 绑定本地 IP 地址和端口
ipAddress.address = "192.168.xxx.xxx";
ipAddress.port = 5445;
tlsOneWay.bind(ipAddress, (err:BusinessError) => {
if (err) {
console.log('绑定失败 2');
return;
}
console.log('绑定成功 2');
});
ipAddress.address = "192.168.xxx.xxx";
ipAddress.port = 8789;
let tlsOneWaySecureOption : socket.TLSSecureOptions = {} as socket.TLSSecureOptions;
tlsOneWaySecureOption.ca = ["xxxx", "xxxx"];
tlsOneWaySecureOption.cipherSuite = "AES256-SHA256";
let tlsOneWayConnectionOption: socket.TLSConnectionOptions = {} as socket.TLSConnectionOptions;
tlsOneWayConnectionOptions.address = ipAddress;
tlsOneWayConnectionOptions.secureOptions = tlsOneWaySecureOption;
// 建立连接
tlsOneWay.connect(tlsOneWayConnectionOption).then(() => {
console.log("连接成功");
}).catch((err: BusinessError) => {
console.log("连接失败" + JSON.stringify(err));
});
// 连接使用完毕后,主动关闭并取消相关事件的订阅
tlsTwoWay.close((err: BusinessError) => {
if (err) {
console.log("关闭错误 = " + err);
} else {
console.log("关闭成功");
}
tlsTwoWay.off('message');
tlsTwoWay.off('connect');
tlsTwoWay.off('close');
});
TCP Socket升级为TLS Socket进行加密数据传输
客户端 TCP Socket 升级为 TLS Socket 进行加密数据传输的步骤如下:- 导入需要的 socket 模块;
- 创建一个 TCPSocket 连接;
- 确保 TCPSocket 已连接后,使用该 TCPSocket 对象创建 TLSSocket 连接,返回一个 TLSSocket 对象;
- 双向认证则上传客户端 CA 证书及数字证书;单向认证则上传客户端 CA 证书;
- 订阅 TLSSocket 相关的订阅事件;
- 发送数据;
- TLSSocket 连接使用完毕后,主动关闭。
客户端 TCP Socket 升级为 TLS Socket 进行加密数据传输的示例代码如下:
import { socket } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
class SocketInfo {
message: ArrayBuffer = new ArrayBuffer(1);
remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo;
}
// 创建一个 TCPSocket 连接,返回一个 TCPSocket 对象
let tcp: socket.TCPSocket = socket.constructTCPSocketInstance();
tcp.on('message', (value: SocketInfo) => {
console.log("监听消息");
let buffer = value.message;
let dataView = new DataView(buffer);
let str = "";
for (let i = 0; i < dataView.byteLength; ++i) {
str += String.fromCharCode(dataView.getUint8(i));
}
console.log("接收消息:" + str);
});
tcp.on('connect', () => {
console.log("连接");
});
// 绑定本地 IP 地址和端口
let ipAddress : socket.NetAddress = {} as socket.NetAddress;
ipAddress.address = "192.168.xxx.xxx";
ipAddress.port = 1234;
tcp.bind(ipAddress, (err: BusinessError) => {
if (err) {
console.log('绑定失败');
return;
}
console.log('绑定成功');
// 连接到指定的 IP 地址和端口
ipAddress.address = "192.168.xxx.xxx";
ipAddress.port = 443;
let tcpConnect: socket.TCPConnectionOptions = {} as socket.TCPConnectionOptions;
tcpConnect.address = ipAddress;
tcpConnect.timeout = 6000;
tcp.connect(tcpConnect, (err: BusinessError) => {
if (err) {
console.log('连接失败');
return;
}
console.log('连接成功');
// 确保 TCPSocket 已连接后,将其升级为 TLSSocket 连接
let tlsTwoWay: socket.TLSSocket = socket.constructTLSSocketInstance(tcp);
// 订阅 TLSSocket 相关的订阅事件
tlsTwoWay.on('message', (value: SocketInfo) => {
console.log("TLS-消息");
let buffer = value.message;
let dataView = new DataView(buffer);
let str = "";
for (let i = 0; i < dataView.byteLength; ++i) {
str += String.fromCharCode(dataView.getUint8(i));
}
console.log("TLS 接收消息:" + str);
});
tlsTwoWay.on('connect', () => {
console.log("tls 连接");
});
tlsTwoWay.on('close', () => {
console.log("tls 关闭");
});
// 配置 TLSSocket 目的地地址、证书等信息
ipAddress.address = "192.168.xxx.xxx"; // 替换为实际目标 IP 地址
ipAddress.port = 1234;
let tlsSecureOption: socket.TLSSecureOptions = {} as socket.TLSSecureOptions;
tlsSecureOption.key = "xxxx"; // 替换为实际的私钥
tlsSecureOption.cert = "xxxx"; // 替换为实际的证书
tlsSecureOption.ca = ["xxxx"]; // 替换为实际的 CA 证书
tlsSecureOption.protocols = [socket.Protocol.TLSv12]; // 指定 TLS 协议版本
tlsSecureOption.useRemoteCipherPrefer = true;
tlsSecureOption.signatureAlgorithms = "rsa_pss_rsae_sha256:ECDSA+SHA256";
tlsSecureOption.cipherSuite = "AES256-SHA256";
let tlsTwoWayConnectionOption: socket.TLSConnectionOptions = {} as socket.TLSConnectionOptions;
tlsSecureOption.key = "xxxx";
tlsTwoWayConnectionOption.address = ipAddress;
tlsTwoWayConnectionOption.secureOptions = tlsSecureOption;
tlsTwoWayConnectionOption.ALPNProtocols = ["spdy/1", "http/1.1"];
// 建立 TLSSocket 连接
tlsTwoWay.connect(tlsTwoWayConnectionOption).then(() => {
console.log("tls 连接成功");
// 连接使用完毕后,主动关闭并取消相关事件的订阅
tlsTwoWay.close((err: BusinessError) => {
if (err) {
console.log("tls 关闭失败=" + err);
} else {
console.log("tls 关闭成功");
}
tlsTwoWay.off('message');
tlsTwoWay.off('connect');
tlsTwoWay.off('close');
});
});
});
});
TLS Socket Server进行加密数据传输
服务端 TLS Socket Server 进行加密数据传输的步骤如下:- 导入需要的 socket 模块;
- 启动服务,绑定 IP 地址和端口号,监听客户端连接,创建并初始化 TLS 会话,加载证书密钥并验证;
- 订阅 TLSSocketServer 的连接事件;
- 收到客户端连接,通过回调得到 TLSSocketConnection 对象;
- 订阅 TLSSocketConnection 相关的事件。
服务端 TLS Socket Server 进行加密数据传输的示例代码:
import { socket } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
let tlsServer: socket.TLSSocketServer = socket.constructTLSSocketServerInstance();
let netAddress: socket.NetAddress = {
address: '192.168.xx.xxx',
port: 8080
}
// 配置 TLS 安全选项
let tlsSecureOptions: socket.TLSSecureOptions = {
key: "xxxx", // 替换为实际的私钥
cert: "xxxx", // 替换为实际的证书
ca: ["xxxx"], // 替换为实际的 CA 证书
password: "xxxx", // 替换为实际的密码
protocols: socket.Protocol.TLSv12, // 使用数组形式指定 TLS 协议版本
useRemoteCipherPrefer: true,
signatureAlgorithms: "rsa_pss_rsae_sha256:ECDSA+SHA256",
cipherSuite: "AES256-SHA256" // 指定加密套件
}
let tlsConnectionOptions: socket.TLSConnectionOptions = {
address: netAddress,
secureOptions: tlsSecureOptions,
ALPNProtocols: ["spdy/1", "http/1.1"]
}
// 启动 TLS 服务器
tlsServer.listen(tlsConnectionOptions).then(() => {
console.log("listen callback success");
}).catch((err: BusinessError) => {
console.log("failed" + err);
});
class SocketInfo {
message: ArrayBuffer = new ArrayBuffer(1);
remoteInfo: socket.SocketRemoteInfo = {} as socket.SocketRemoteInfo;
}
let callback = (value: SocketInfo) => {
let messageView = '';
for (let i: number = 0; i < value.message.byteLength; i++) {
let uintArray = new Uint8Array(value.message);
let messages = uintArray[i];
let message = String.fromCharCode(messages);
messageView += message;
}
console.log('on message message: ' + JSON.stringify(messageView));
console.log('remoteInfo: ' + JSON.stringify(value.remoteInfo));
}
// 客户端连接处理
tlsServer.on('connect', (client: socket.TLSSocketConnection) => {
client.on('message', callback); // 订阅消息事件
// 发送数据
client.send('Hello, client!').then(() => {
console.log('send success');
}).catch((err: BusinessError) => {
console.log('send fail');
});
// 断开连接
client.close().then(() => {
console.log('close success');
}).catch((err: BusinessError) => {
console.log('close fail');
});
// 可以指定传入 on 中的 callback 取消一个订阅,也可以不指定 callback 清空所有订阅
client.off('message', callback);
client.off('message');
});
// 取消订阅 tlsServer 的相关事件
tlsServer.off('connect');
ICP备案:
公安联网备案: