HarmonyOS 鸿蒙Next使用ArkTS TCP Socket接收数据不全
HarmonyOS 鸿蒙Next使用ArkTS TCP Socket接收数据不全
RT。
目前基于API9开发TCP socket的数据收发功能,但是数据总是收不全(大概就几K的数据),应该有一半的数据没发过来。
同样的服务器环境,Android就没问题,有谁知道什么原因吗?
以下是代码参考开源的例子:
import socket from ‘@ohos.net.socket’;
import Logger from ‘…/utils/Logger’;
const TAG = ‘TcpSocket’;
export default class TcpSocket {
private tcpSocket: socket.TCPSocket | null = null;
/**
-
创建Socket
-
@param localIp
-
@param port
*/
async createSocket(localIp: string, port: number): Promise<boolean> {
Logger.info(${TAG} tcp bind localIp: ${localIp}
);
try {
if (this.tcpSocket) {
this.tcpSocket.close();
this.tcpSocket = null;
}
this.tcpSocket = socket.constructTCPSocketInstance();
await this.tcpSocket.bind({
address: localIp,
port: port,
family: 1
});
Logger.info(${TAG} tcp bind sucess
);
return true;
} catch (e) {
Logger.error(${TAG} tcp bind error ${<span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(e)}}
);
}
return false;
}
/**
-
连接Socket
-
@param address
-
@param port
*/
async connectSocket(address: string, port: number): Promise<boolean> {
Logger.info(${TAG} tcp connectSocket address: ${address}
);
try {
if (!this.tcpSocket) {
return false;
}
if (await this.isConnected()) {
Logger.info(${TAG} tcp connectSocket sucess
);
return true;
}
await this.tcpSocket.connect({
address: {
address: address,
port: port,
family: 1,
},
timeout: 6000,
});
await this.tcpSocket.setExtraOptions({});
Logger.info(${TAG} tcp connectSocket sucess
);
return true;
} catch (e) {
Logger.error(${TAG} tcp connectSocket error ${<span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(e)}}
);
}
return false;
}
/**
- 关闭Socket
*/
async closeSocket(): Promise<void> {
if (!this.tcpSocket) {
return;
}
await this.tcpSocket.close();
this.tcpSocket.off(‘connect’);
this.tcpSocket.off(‘message’);
this.tcpSocket = null;
}
/**
- 发送数据
- @param data
*/
async sendData(data: string): Promise<void> {
if (!this.tcpSocket) {
return;
}
Logger.info(
${TAG} tcp sendData data ${<span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(data)}
);
try {
await this.tcpSocket.send({
data: data,
});
} catch (e) {
Logger.error(${TAG} tcp sendData error ${<span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(e)}}
);
}
}
/**
- 判断是否连接
*/
async isConnected(): Promise<boolean> {
if (!this.tcpSocket) {
return false;
}
<span class="hljs-keyword"><span class="hljs-keyword">try</span></span> {
<span class="hljs-keyword"><span class="hljs-keyword">let</span></span> state = await <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.tcpSocket.getState();
<span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (state.isConnected) {
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> <span class="hljs-literal"><span class="hljs-literal">true</span></span>;
}
} <span class="hljs-keyword"><span class="hljs-keyword">catch</span></span> (e) {
Logger.error(`${TAG} tcp getState error ${<span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(e)}}`);
}
<span class="hljs-keyword"><span class="hljs-keyword">return</span></span> <span class="hljs-literal"><span class="hljs-literal">false</span></span>;
}
/**
- 订阅消息
- @param callback
*/
setOnMessageReceivedListener(callback: (buffer: ArrayBuffer) => void): void {
if (!this.tcpSocket) {
return;
}
<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.tcpSocket.on(<span class="hljs-string"><span class="hljs-string">'message'</span></span>, (data) => {
Logger.info(`${TAG} TCP data: ` + <span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(data));
<span class="hljs-keyword"><span class="hljs-keyword">let</span></span> buffer = data.message;
callback(buffer);
});
}
/**
- TCP 关闭事件订阅
- @param callback
*/
setOnCloseListener(callback: () => void): void {
Logger.info(
${TAG} TCP setOnCloseListener into
);
this.tcpSocket?.on(‘close’, () => {
Logger.info(${TAG} TCP setOnCloseListener onClose:
);
callback();
this.closeSocket();
});
<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.tcpSocket?.on(<span class="hljs-string"><span class="hljs-string">'error'</span></span>, (data) => {
Logger.info(
`${TAG} TCP setOnCloseListener onClose:` + <span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(data)
);
callback();
<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.closeSocket();
});
}
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>
更多关于HarmonyOS 鸿蒙Next使用ArkTS TCP Socket接收数据不全的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
更多关于HarmonyOS 鸿蒙Next使用ArkTS TCP Socket接收数据不全的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
setOnMessageReceivedListener(callback: SocketCallback): void { if (!this.tcpSocket) { return; } let messageView = ‘’;
this.tcpSocket.on('message', (value) => {
LogUtil.e(TAG, "Socket请求setOnMessageReceivedListener: " + JSON.stringify(value));
if (value) {
LogUtil.e(TAG, "Socket请求setOnMessageReceivedListener buffer.byteLength: " + value.message.byteLength);
// let messageView = new Uint8Array(value.message.byteLength);
//
// for (let i: number = 0; i < value.message.byteLength; i++) {
//
// let uint8Array = new Uint8Array(value.message)
// //let messages = uint8Array[i]
// //let message = String.fromCharCode(messages);
// //messageView += message;
// messageView.set(uint8Array,startlegth);
// startlegth++
// }
// let buffer = data.message;
// LogUtil.e(TAG, "Socket请求setOnMessageReceivedListener buffer.byteLength: " + buffer.byteLength);
for (let i: number = 0; i < value.message.byteLength; i++) {
let uint8Array = new Uint8Array(value.message)
let messages = uint8Array[i]
let message = String.fromCharCode(messages);
messageView +=message;
}
if (messageView) {
LogUtil.e(TAG, "Socket请求setOnMessageReceivedListener messageView: " + messageView);
callback.callback(StringUtils.stringToUint8Array(messageView));
}else{
callback.callback(null!);
}
}else{
callback.callback(null!);
}
});
}
可能是因为所谓的TCP“粘包”问题,TCP是一种面向流的数据传输协议,传输的对象是连续的字节流,内容之间并没有明确的分界标志,严格来说,并不存在粘包的问题,而通常所说的粘包,更多的是一种逻辑上的概念,也就是人为的把TCP传输的字节流划分成了一个个的数据包,发送端确定了数据包之间的边界,但是接收端并不能保证按照数据包的边界来接收。
详细原因分析可以见我之前写的一个帖子:
this.tcpSocket.on('message', (data) => {
Logger.info(`${TAG} TCP data: ` + JSON.stringify(data));
let buffer = data.message;
callback(buffer);
// 试试在这儿加个 Logger.info 看看确认 callback 已经被完整执行了? 相当奇怪的问题.
// 传入的 callback 函数是异步的吗? 我对 ts 异步不太熟悉
// 是不是需要 await 一下 callback(buffer)
Logger.info(`${TAG} TCP data consumed.`);
});
学习
针对HarmonyOS鸿蒙Next使用ArkTS TCP Socket接收数据不全的问题,这可能是由于多种原因导致的。以下是一些可能的解决方案:
- 检查网络稳定性:确保网络连接稳定,TCP连接依赖于稳定的网络连接,网络波动可能导致数据丢失。
- 调整接收缓冲区大小:如果接收缓冲区设置过小,可能无法容纳完整的数据包。可以尝试增加接收缓冲区的大小。
- 处理粘包和拆包问题:TCP是面向流的协议,不存在消息边界,可能会导致粘包和拆包现象。需要在应用层进行协议设计,确保能够正确解析数据。
- 检查数据发送方:确认数据发送方是否完整发送了数据,以及是否设置了合理的发送缓冲区大小。
如果以上方法均未能解决问题,可能是TCP Socket实现上的特定问题。此时,建议深入检查TCP Socket的实现细节,或者考虑使用其他网络通信库。如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html。