HarmonyOS 鸿蒙Next使用ArkTS TCP Socket接收数据不全

发布于 1周前 作者 gougou168 来自 鸿蒙OS

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) =&gt; {
  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) =&gt; {
  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

8 回复
解决了吗?

更多关于HarmonyOS 鸿蒙Next使用ArkTS TCP Socket接收数据不全的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


我也遇到了,TCP Socket接收数据概率性出现数据错位、数据不完整

setOnMessageReceivedListener(callback: SocketCallback): void { if (!this.tcpSocket) { return; } let messageView = ‘’;

this.tcpSocket.on('message', (value) =&gt; {
  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 &lt; 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 &lt; 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!);
  }
});

}

使用C Socket接收,回调上来用ArkTS来解析

可能是因为所谓的TCP“粘包”问题,TCP是一种面向流的数据传输协议,传输的对象是连续的字节流,内容之间并没有明确的分界标志,严格来说,并不存在粘包的问题,而通常所说的粘包,更多的是一种逻辑上的概念,也就是人为的把TCP传输的字节流划分成了一个个的数据包,发送端确定了数据包之间的边界,但是接收端并不能保证按照数据包的边界来接收。

详细原因分析可以见我之前写的一个帖子:

鸿蒙网络编程系列6-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接收数据不全的问题,这可能是由于多种原因导致的。以下是一些可能的解决方案:

  1. 检查网络稳定性:确保网络连接稳定,TCP连接依赖于稳定的网络连接,网络波动可能导致数据丢失。
  2. 调整接收缓冲区大小:如果接收缓冲区设置过小,可能无法容纳完整的数据包。可以尝试增加接收缓冲区的大小。
  3. 处理粘包和拆包问题:TCP是面向流的协议,不存在消息边界,可能会导致粘包和拆包现象。需要在应用层进行协议设计,确保能够正确解析数据。
  4. 检查数据发送方:确认数据发送方是否完整发送了数据,以及是否设置了合理的发送缓冲区大小。

如果以上方法均未能解决问题,可能是TCP Socket实现上的特定问题。此时,建议深入检查TCP Socket的实现细节,或者考虑使用其他网络通信库。如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部