C 二进制包中的转义字符(0x1b/27)不';无法通过Wi-Fi发送,且在传输过程中信息已损坏

C 二进制包中的转义字符(0x1b/27)不';无法通过Wi-Fi发送,且在传输过程中信息已损坏,c,embedded,protocol-buffers,nanopb,C,Embedded,Protocol Buffers,Nanopb,我正在开发一个嵌入式系统(STM32F4),我试图将一些数据发送到PC端的一个简单的Windows窗体客户端程序。当我使用基于字符的字符串格式时,一切正常,但当我改为二进制软件包以提高性能时,我遇到了转义字符的问题 我使用nanopb来实现Googles协议缓冲区的传输,我发现在5%的包中,我在客户端程序中收到异常,告诉我包被破坏了 我在WireShark中调试,发现这个损坏的包的大小比原始包的大小小2-4字节。在进一步检查后,我发现损坏的包始终包含二进制值27,而其他包从未包含此值。我搜索了它

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

我使用nanopb来实现Googles协议缓冲区的传输,我发现在5%的包中,我在客户端程序中收到异常,告诉我包被破坏了

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

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


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

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

// 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>
//每个转义序列都以ASCII字符27(0x1B)开头,
//等效于ESC键。<>的内容是字节或字节流。
//-Cid是连接id(udp、tcp等)
//-数据长度为4 ASCII字符表示十进制值
//也就是说,1400字节将是“1”“4”“0”“0”(0x31 0x34 0x30 0x30)。
//-数据大小必须与指定的长度匹配。
//忽略数据有效载荷之间的所有命令或esc序列。
Z
注意有关数据大小的备注:“忽略数据有效负载之间的所有命令或esc序列”

例如,以下是

// 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);
//包括snprintf坚持要写入的尾随0
uint8_t头[8];
//准备标题:Z
snprintf((char*)头,sizeof(头),“\x1bZ%x%04d”,cid,len);
//首先,将转义序列写入cid。在此之后
//模块以O或F响应。
writeRaw(头,3);
如果(!readDataResponse()){
如果(GS_日志_错误&&this->error)
此->错误->打印项次(“发送批量数据帧失败”);
返回false;
}
//然后,写入转义序列的其余部分(-1)以不写入
//尾随0)
writeRaw(header+3,sizeof(header)-1-3)+
//并写出实际数据
writeRaw(buf,len);

这很可能会奏效。或者,一个肮脏的黑客可能是在发送前“转义转义字符”,即在发送前用两个字符(0x27 0x27)替换每个0x27-但这只是一个猜测,我认为您应该查看手册。

我正在使用库nanopb打包数据。谢谢你,我会尝试你的想法,然后报告它是否有效!非常感谢。您关于数据大小的建议使我找到了问题的根源。我使用了消息类型:UCID远程地址:远程端口:之前,但我更改为Y远程地址:远程端口:。包含数据大小会阻止模块执行转义字符!