Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/visual-studio-code/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
TCL中的二进制扫描格式8位字符代码(c)_Tcl - Fatal编程技术网

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

TCL中的二进制扫描格式8位字符代码(c),tcl,Tcl,我对类型“c”的二进制扫描感到困惑,因为据说“c”是指8位字符代码。我有以下代码需要维护 puts "" set b_val2 "0000021002020a042845245d868a8d9900081b000315aef0010c105d39b4f7c9a083a65e7d000306140508063024" set msg2 [binary format H* $b_val2] set msg2 [string range $msg2 1 end]

我对类型“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,它试图获取范围)对于初学者来说,第二次输入失败的原因是:您的代码片段在
while
循环中从不修改
msg2
,因此
扫描
每次循环都返回相同的结果,并且您有一个无限循环。我只在循环中抛出了一次
中断
,但这让我不确定我是否有正确的行为

也就是说,显而易见的问题是,当您从原始消息转到替换消息时,您删除了第一个字节(值00)。从第2行开始(忽略空行),在该行中设置

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

现在使用的输入重新分析

set b_val2 "00021002020903e84..."
从第二行输入。同样,第4行中的第一个字节被丢弃,留给您的是
\x02\x10\x02\x02\x09\x03…
。第5行将id2设置为2,将len2设置为
\x10
,或十进制16,这就是您看到的。这意味着val2与您期望的非常不同,但这是因为您从输入中删除了一个字节


字节分析器对字符串中的初始位置非常敏感。一旦你搞砸了,你最好有一个强大的再同步机制,否则一切都完了。这是有线协议困难的一个主要原因。:)

这也是有线协议通常是文本的原因之一;它们往往很容易重新同步(以需要更多带宽为代价)。我最近最喜欢的一个是Netstrings(),它是一种大小合理的文本包装结构。我在终止逗号之前添加了一个2字节的CRC,这也使它们具有合理的错误安全性。