如何通过Dart TCP套接字发送原始字节

11

我被卡在了我能想到的最愚蠢的障碍上。我正在开发一个flutter应用程序,它应该通过TCP套接字(在本地wifi网络上)发送一组字节。

这些字节是原始的,并不代表任何编码中的有意义的字符(我有像0xFF等值)。我的代码成功地连接并使用socket的write方法发送数据。不幸的是,该方法只接受一个已编码的String作为参数,并且从char codes创建一个字符串会破坏我的消息。

以下是我的代码:

var message = Uint8List(4);
var bytedata = ByteData.view(message.buffer);

bytedata.setUint8(0, 0x01);
bytedata.setUint8(1, 0x07);
bytedata.setUint8(2, 0xFF);
bytedata.setUint8(3, 0x88);

socket.write(String.fromCharCodes(message))

当接收到0x01和0x07时,它们被正确解析,但是0xFF和0x88则转换成了另外两个字节,即0xC3BF和0xC287(使用netcat -l 8080 | hexdump 命令检查)。

我已经搜索了一段时间,想找到不将原始字节编码为字符串的方法,但是没有找到。难道这根本没有被考虑过吗?我知道Flutter和Dart是用于高级Web开发的,但我觉得这太荒谬了。

2个回答

19

显然可以不考虑编码方式就写入字节;但是谷歌搜索可能无法立即找到答案,这可能是因为没有其他人提出过这个问题,而该函数本身没有明显的名称或描述。

Dart中的Socket类继承自IOSink类,后者拥有add()方法恰好符合我的需求。

来自文档:

void add (List<int> data) 

Adds byte data to the target consumer, ignoring encoding.
The encoding does not apply to this method, and the data list is passed directly to the target consumer as a stream event.
This function must not be called when a stream is currently being added using addStream.
This operation is non-blocking. See flush or done for how to get any errors generated by this call.

The data list should not be modified after it has been passed to add.

https://api.dartlang.org/stable/2.0.0/dart-io/Socket-class.html

正确的代码只是简单的

var message = Uint8List(4);
var bytedata = ByteData.view(message.buffer);

bytedata.setUint8(0, 0x01);
bytedata.setUint8(1, 0x07);
bytedata.setUint8(2, 0xFF);
bytedata.setUint8(3, 0x88);

socket.add(message)

1
谢谢。这在2020年仍然很相关。尽管我喜欢在Flutter中开发——热重载、易于状态管理等等,但它仍然缺乏重要的低级功能和适当的文档。 在尝试使用RawServerSocketRawSocket后,我找到了这个Socket部分。不幸的是,我找到的示例并没有帮助我。这个答案给了我一个很好的替代方案,它真的应该出现在主页面上——谢谢。 - Ethan K
1
你节省了我的时间!非常感谢! - AMK

1

优化方案

   import 'dart:typed_data';
    
    ///This class is useful to convert Hex String to ByteArray
    class Hex {
      ///Return [Uint8List] i.e byte array from the
      ///hex string. Hex string should be greter than or equal to
      ///2.
      static Uint8List toByteList(String hexString) {
        var message = Uint8List(hexString.length ~/ 2);
        var bytedata = ByteData.view(message.buffer);
        int counter = 0, i = 0;
        while (counter < hexString.length / 2) {
          String str = hexString.substring(i, i += 2);
          bytedata.setUint8(counter++, int.parse('0x$str'));
        }
        return message;
      }
    }

使用 ::

Uint8List message = Hex.toByteList('0107FF88');
socket?.add(message);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接