首页 > 解决方案 > 在线从 uint8List 构造基于行的 ByteBuffer

问题描述

我想我的问题很简单,但我是飞镖新手......

情况

这只是基本代码和工作。

main() async {
  await SecureSocket.connect('SERVER', 123).then(handleResponse);
}

void handleResponse(SecureSocket ss) {

  print('Connected to: '
      '${ss.remoteAddress.address}:${ss.remotePort}');

  ss.listen(
      (data) {
          print ('New chunk available:' + data.lengthInBytes.toString() + ' Bytes');
          String msg = String.fromCharCodes(data).trim();
          print(data.toString());
      },
      onDone: () {
          ss.destroy();
      },
      onError: (error) {
        print('An Error occured while communicating with the server.');
      },
      cancelOnError: true,
  );

  ss.write('FGG1223' + '\r\n');
}

现在,我想用传入的数据逐步更新我的前端。这就是为什么我想在数据到达后立即开始解析和处理数据。

从语义的角度来看,数据中的分隔符是CRLF [13,10]。
它将命令序列彼此分开,例如:
CMD1CMD2CRLFCMD3CRLF

因此,我的想法是将到达的数据基于行存储,由 CRLF 分隔在另一个缓冲区(ByteBuffer List)中。
数据会更容易处理(为解析器提供数据),而且我可以更早地更新前端。

问题

在这种情况下,我必须等到下一个 LF 到达下一个块之一,或者如果 LF 在 n 个块之后没有到达,则抛出异常。

在 dart 中是否有一种简单而优雅的方法来实现这一点?

谢谢你。

时间 0,1,2 的示例服务器响应 0
块:[ 32,79,101,97,100,13,10,121,46,13,10 ] 1 块:[ 70,76,65,71,13 ] 2 块:[ 10 , 66, 89, 69, 32, 13 , 10 ]


标签: socketsdartbuffer

解决方案


我知道我建议的解决方案不能 100% 符合您的要求,但我希望它仍然能给解决方案带来一些启发。我没有编写处理数据块拆分的所有逻辑,而是使用 Dart SDK 中的方法制作了这个示例:

import 'dart:convert';
import 'dart:io';

Future<void> main() async {
  await SecureSocket.connect('SERVER', 123).then(handleResponse);
}

void handleResponse(SecureSocket ss) {
  print('Connected to: ${ss.remoteAddress.address}:${ss.remotePort}');

  ss
      .map((uint8list) => uint8list.toList())
      .transform(const Utf8Decoder())
      .transform(const LineSplitter())
      .listen(
    (line) {
      print('New line available:' + line);
    },
    onDone: () {
      ss.destroy();
    },
    onError: (Exception error) {
      print('An Error occured while communicating with the server.');
    },
    cancelOnError: true,
  );

  ss.write('FGG1223\r\n');
}

首先,我要注意,该map方法的使用用于将Uint8List(由SecureSocket类使用)转换List为由Utf8Decoder. 我希望这在未来的 Dart 版本中是不必要的,因为它看起来有点傻。

然后我将接收到的字节转换为 UTF8 并将其发送到LineSplitter从块中返回行的 a。

所有这些都在接收到数据时起作用。因此,listen每次解析整行时都会触发您的方法。

同样,这并不完全像您想要的那样。但我希望它能给一个可行的解决方案带来一些启发。如果您想根据您的要求制作更具体的东西,您可以查看如何制作自己的StreamTransformer.


推荐阅读