2025-07-22 14:26:37 +08:00

152 lines
4.2 KiB
Plaintext

import socket from '@ohos.net.socket'
import { BusinessError } from '@ohos.base'
import { TCPTag } from '../config'
export default class TcpClient {
private static instance: TcpClient
private localIp: string = ''
private localIpPort: string = ''
private oppositeIp: string = ''
private oppositeIpPort: string = ''
private tcpSendNum: number = 0
private tcp: socket.TCPSocket = socket.constructTCPSocketInstance()
private events: Array<Function> = []
// 连接状态是否成功
private linkStatus: boolean = false
constructor() {
if (!TcpClient.instance) {
TcpClient.instance = this
}
return TcpClient.instance
}
// 初始化tcp连接
async init(tcpLocalIp: string, tcpLocalIpPort: string, tcpOppositeIp: string, tcpOppositePort: string) {
this.localIp = tcpLocalIp
this.oppositeIp = tcpOppositeIp
this.localIpPort = tcpLocalIpPort
this.oppositeIpPort = tcpOppositePort
console.log(TCPTag, 'new Tcp', this.localIp, this.localIpPort, this.oppositeIp, this.oppositeIpPort)
this.tcp = socket.constructTCPSocketInstance();
await this.bindTcp()
await this.connectTcp()
}
// 绑定tcp
bindTcp(): Promise<Boolean> {
return new Promise((resolve, reject) => {
this.tcp.bind({
address: this.localIp,
port: Number(this.localIpPort),
family: 1
}).then(() => {
console.log(TCPTag, 'bindTcp success:', this.localIp, this.localIpPort, this.oppositeIp, this.oppositeIpPort)
resolve(true)
}).catch((err: BusinessError) => {
console.log(TCPTag, 'bindTcp error:', JSON.stringify(err), this.localIp, this.localIpPort, this.oppositeIp, this.oppositeIpPort)
reject(err)
})
})
}
// 连接tcp
connectTcp(): Promise<Boolean> {
return new Promise((resolve, reject) => {
this.tcp.connect({
address: {
address: this.oppositeIp, port: Number(this.oppositeIpPort), family: 1
}, timeout: 1000 * 15
})
.then(() => {
this.linkStatus = true
this.getMessage()
console.log(TCPTag, "tcp connect success")
return this.tcp.setExtraOptions({
keepAlive: true
})
})
.then(() => {
resolve(true)
})
.catch((err: BusinessError) => {
this.linkStatus = false
console.log(TCPTag, "tcp connect or keepAlive error: ", JSON.stringify(err))
console.log(TCPTag, "tcp 重启服务")
reject(err)
})
})
}
getMessage() {
if (!this.linkStatus) {
console.log(TCPTag, '不允许获取消息: TCP未连接');
return;
}
this.tcp.on("message", value => {
let data = new DataView(value.message)
this.events.forEach(cb => {
// TODO
// 一体机不需要截取
cb(value.message.slice(5, data.byteLength))
})
})
}
// 重新绑定tcp
async reBind() {
console.log(TCPTag, 'tcp rebind')
await this.close()
this.tcp = socket.constructTCPSocketInstance();
await this.bindTcp()
await this.connectTcp()
}
// 监听tcp错误
onError(callback: Function) {
this.tcp.on('error', err => {
console.log(TCPTag, 'tcp on error: ', JSON.stringify(err))
callback?.()
});
}
// 关闭tcp连接
close(): Promise<void> {
return this.tcp?.close()
}
// 监听tcp消息
onMsg(callback: Function) {
if (this.events.includes(callback)) {
console.log(TCPTag, '已经存在这个获取消息方法了');
return;
}
this.events.push(callback);
}
// 接收tcp消息
sendMsg(data: string): Promise<void> {
if (!this.linkStatus) {
console.log(TCPTag, '不允许发送: TCP未连接');
return Promise.reject(new Error('TCP connection is not established'));
}
return this.tcp?.send({
data
}).catch(async (err: BusinessError) => {
console.log(TCPTag, 'sendMsg error:', JSON.stringify(err), this.oppositeIp, this.oppositeIpPort)
this.tcpSendNum++
if (this.tcpSendNum > 10) {
this.tcpSendNum = 0
await this.reBind()
}
return Promise.reject(err)
})
}
// 取消监听tcp消息
offMsg(callback: Function) {
this.events = this.events.filter(cb => cb !== callback)
}
}