c - 二进制包中的转义字符 (0x1b/27) 不会通过 Wi-Fi 发送,并且在传输过程中会损坏消息

标签 c embedded protocol-buffers nanopb

我正在嵌入式系统(STM32F4)上进行开发,我尝试将一些数据发送到PC端的简单Windows Forms客户端程序。当我使用基于字符的字符串格式时,一切工作正常,但是当我更改为二进制包以提高性能时,我遇到了转义字符的问题。

我正在使用 nanopb 来实现 Google Protocol Buffer 进行传输,并且我观察到,在 5% 的包中,我在客户端程序中收到异常,告诉我我的包已损坏。

我在 WireShark 中进行调试,发现这个损坏的包的大小比原始包的大小小 2-4 个字节。经过进一步检查,我发现损坏的包始终包含二进制值 27,而其他包从未包含该值。我搜索了一下,发现这个值代表一个转义字符,这可能会导致问题。

我正在使用的 Wi-Fi 模块(Gainspan GSM2100)的技术文档提到命令前面有转义字符,因此我认为我需要在包中删除这些值。

我找不到问题的解决方案,因此如果更有经验的人能够引导我找到解决此问题的正确方法,我将不胜感激。

最佳答案

你如何发送数据?您正在使用库或发送原始字节吗?根据the manual ,您的数据命令应以转义序列开头,但还指定了数据长度:

// Each escape sequence starts with the ASCII character 27 (0x1B),
// the equivalent to the ESC key. The contents of < > are a byte or byte stream.
// - Cid is connection id (udp, tcp, etc)
// - Data Length is 4 ASCII char represents decimal value
//   i.e. 1400 bytes would be '1' '4' '0' '0' (0x31 0x34 0x30 0x30).
// - Data size must match with specified length. 
//   Ignore all command or esc sequence in between data pay load.
<Esc>Z<Cid><Data Length xxxx 4 ascii char><data>

请注意有关数据大小的注释:“忽略数据负载之间的所有命令或 esc 序列”

例如, GSCore::writeData function in GSCore.cpp 就是这样的看起来像:

// Including a trailing 0 that snprintf insists to write
uint8_t header[8]; 

// Prepare header: <esc> Z <cid> <ascii length>
snprintf((char*)header, sizeof(header), "\x1bZ%x%04d", cid, len);

// First, write the escape sequence up to the cid. After this, the
// module responds with <ESC>O or <ESC>F.
writeRaw(header, 3);

if (!readDataResponse()) {
    if (GS_LOG_ERRORS && this->error)
        this->error->println("Sending bulk data frame failed");
    return false;
}

// Then, write the rest of the escape sequence (-1 to not write the
// trailing 0)
writeRaw(header + 3, sizeof(header) - 1 - 3);+

// And write the actual data
writeRaw(buf, len);

这应该很可能有效。或者,一个肮脏的黑客可能是在发送之前“转义转义字符”,即在发送之前用两个字符(0x27 0x27)替换每个0x27 - 但这只是一个疯狂的猜测,我假设你应该只检查手册。

关于c - 二进制包中的转义字符 (0x1b/27) 不会通过 Wi-Fi 发送,并且在传输过程中会损坏消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36979543/

相关文章:

c++ - OpenCV 3.2 包括与 protobuf 3.1 冲突的 libmir* 和 protobuf 2.6

java - Protocol Buffer : get byte array from ByteString without copying

c++ - Visual Studio 将 "filter"编译为 C,将 "filters"组编译为 C++

c - 我缺少什么,所以我可以编译我的源代码?我是新手

c - -I/path 和 -L/path 放入代码中

c++ - 如何使用x86汇编访问c中main函数中的变量

assembly - 如何在 Linux 驱动程序中切换到实模式

embedded - 您如何在嵌入式项目中组织代码?

c - Nucleo STM32F7 上的 UDP 回显

android - 数据结构的最快序列化/反序列化模式