二进制扫描格式TCL中的8位字符代码(c)

时间:2014-05-17 09:09:39

标签: tcl

我对类型“c”的二进制扫描感到困惑,因为据说“c”指的是8位字符代码。我有以下代码要维护

   puts ""
     set b_val2 "0000021002020a042845245d868a8d9900081b000315aef0010c105d39b4f7c9a083a65e7d000306140508063024"
    set msg2 [binary format H* $b_val2]
    set msg2 [string range $msg2 1 end]  


   while {[binary scan $msg2 cc id2 len2] == 2} {
     puts ""
     #puts "SECOND ID is $id2 and SECOND LENGTH is $len2"

     set id2 [expr {$id2 & 0xff}]        
     set len2 [expr {$len2 & 0xff}]
     set val2 [string range $msg2 2 [expr {1+$len2}]]

     switch -exact -- $id2 {
                0 {
                  puts ""
                   if {$val2 == "\x10\x04"} {   
                     puts "val is found for 04 "
                   } elseif {$val2 == "\x10\x02"} {
                     puts "ID is found for 02! CORRECT "
                   } else {
                     puts "not supported"
                   }
                }
     }
   }

这个想法是从给定的十六进制中取“10 02”的值。并且这段代码工作正常,直到我将b_val的给定输入更改为

00021002020903e845245ca0d29858081c00031ef7c001106d3931e7d3414e6d3df26831030614051608045c22

对于第一个给定的十六进制代码“len”是“3”并且它正确地解析二进制文件,但对于第二个十六进制输入,“len2”是16,因此解析错误的字节。

我读到二进制扫描cc将返回两个8位字符代码的变量,但上面的失败根本没有任何意义,正如我所理解的那样,前一作者试图瞄准的是什么上面的代码(特别是它尝试取范围的set val2)以及第二次输入失败的原因

1 个答案:

答案 0 :(得分:1)

对于初学者:您的代码段永远不会在msg2循环中修改while,因此scan会在每个循环中返回相同的结果,并且您有一个无限循环。我抛出一个break只进行一次循环,但这让我不确定我是否有正确的行为。

尽管如此,显而易见的问题是,当您从原始消息转到替换消息时,您已删除了第一个字节(值为00)。从第2行(忽略空白行)开始,在此处设置

set b_val2 "0000021002020a..."

让我们手工解析。第3行将其转换为十六进制,第4行删除第一个字节,以便我们以十六进制值\x00 \x02 \x10 \x02 \x02 \x0a ...的字节串开头。第5行的binary scan将id2设置为第一个字节,将len2设置为第二个字节;第10行将val2设置为值为\x10 \x02的字符串,该字符串符合您的条件。成功。

现在使用

的输入进行重新分析
set b_val2 "00021002020903e84..."

来自您的第二个输入行。同样,第4行的第一个字节是DISCARDED,只剩下\x02 \x10 \x02 \x02 \x09 \x03...。第5行将id2设置为2,将len2设置为\x10或十进制16,这是您所看到的。这意味着val2与您的预期非常不同,但这是由于您从输入中删除了一个字节。

字节解析器对字符串中的初始位置非常敏感。一旦你搞砸了,你最好有一个强大的重新同步机制,或者它完全禁止喊叫。这是线路协议困难的一个主要原因。 :)