Dart客户端向C++服务器通过TCP发送4字节浮点数失败求助
问题根源与解决方案
你的问题出在将二进制字节数据转换为String后再用UTF-8编码发送的环节上。当你用String.fromCharCode把浮点数的4字节二进制数据转成字符串时,很多字节值并不是合法的UTF-8字符——UTF-8对字符编码有严格规则,无效的字节会被UTF-8编码器替换成多字节的替代字符(比如�,占3字节),这就导致原本4字节的浮点数数据被编码成了7字节,C++端自然无法正确解析。
正确的做法:直接发送原始二进制数据
不要把二进制数据(整数、浮点数的字节)转成String,而是直接拼接所有部分的Uint8List,然后发送这个原始的二进制字节数组。这样能保证每个部分的字节数完全符合预期,不会被UTF-8编码篡改。
修改后的代码示例
首先重构DataPacket类,让它生成完整的二进制字节列表,而不是字符串:
import 'dart:convert'; import 'dart:typed_data'; class DataPacket { String message = "some"; int ID = 1; double x = 1.38; Uint8List toBytes() { // 将字符串转换为UTF-8字节(这部分是安全的,因为字符串本身就是UTF-8兼容的) Uint8List messageBytes = utf8.encode(message); // 生成ID的2字节小端序字节数组 Uint8List idBytes = _getInt16LittleEndianBytes(ID); // 生成浮点数的4字节小端序字节数组(注意和C++端保持字节序一致) Uint8List xBytes = Uint8List(4)..buffer.asByteData().setFloat32(0, x, Endian.little); // 拼接所有字节数组 final totalLength = messageBytes.length + idBytes.length + xBytes.length; Uint8List result = Uint8List(totalLength); int offset = 0; // 复制消息字节 result.setRange(offset, offset + messageBytes.length, messageBytes); offset += messageBytes.length; // 复制ID字节 result.setRange(offset, offset + idBytes.length, idBytes); offset += idBytes.length; // 复制浮点数字节 result.setRange(offset, offset + xBytes.length, xBytes); return result; } Uint8List _getInt16LittleEndianBytes(int value) => Uint8List(2)..buffer.asByteData().setInt16(0, value, Endian.little); }
然后修改发送逻辑,直接发送生成的二进制数据:
void sendMessage() { Uint8List data = DataPacket().toBytes(); print("Total bytes to send: ${data.length}"); // 应该是4("some")+2+4=10字节 _socket.add(data); }
额外注意事项
- 字节序一致性:确保Flutter端生成的字节序(小端/大端)和C端解析时使用的字节序完全一致。上面的代码用了
Endian.little,C端解析时也要用小端序处理浮点数和整数。 - C++端解析:现在你可以直接在C++端用
memcpy把接收到的字节复制到对应类型的变量中,比如:// 假设已经接收到完整的数据包 char message[5]; // "some" + 结束符 int16_t ID; float x; memcpy(message, buffer, 4); message[4] = '\0'; // 手动加字符串结束符 memcpy(&ID, buffer+4, 2); // 如果C++端是小端系统,直接用;大端的话需要转换字节序 memcpy(&x, buffer+6, 4);
内容的提问来源于stack exchange,提问作者Jaehyung Kim
相关产品推荐
相关产品推荐

