使用校验和将字节数组转换为字符串。在 python 中重新迭代时获取额外的空字节

Posted

技术标签:

【中文标题】使用校验和将字节数组转换为字符串。在 python 中重新迭代时获取额外的空字节【英文标题】:Convert byte array to string with a checksum. Getting additional null bytes on re-iteration in python 【发布时间】:2013-12-04 15:26:33 【问题描述】:

好的,这是我的问题。实际上是两个。

在第一次通过后运行我的代码时,我得到了额外的空字节,我做错了什么?

第二个问题,如何从字节数组和添加校验和形成数据包?

我有一个字节数组,我需要对其进行 XOR 以获得校验和值。 XOR 之前的起始校验和必须为 5A。这需要附加到数组的末尾并发送到我的外部设备。

我“认为”我这样做是对的,但我没有得到设备的响应。我已经检查了设备并且它工作正常,所以我假设它是我的代码。

因此,我已经提出了下面的代码。任何帮助形成要发送的数据包都会非常有帮助,因为我一直把头撞在墙上。我不是一个非常有经验的 Python 程序员,但我通常可以在解释或给出示例时弄清楚。

import struct
import sys
import string
import select
import time
from socket import *
import binascii


port = 8010
# region Read Codes
getBoardTemp = [0x02, 0x53, 0x00, 0x00]
#Communication utilities

class CommUtilities:
    def unhex(self, inp):
        return binascii.unhexlify(inp)

    def hexit(self, inp):
        return binascii.a2b_hex(inp)

    def calculateChecksum(self, buf):
        checksum = 0x5A #Starting checksum
        #For each byte, bitwise XOR it with our checksum
        for b in buf:
            checksum ^= b
        print 'Checksum: '.format(checksum)
        return checksum

    #Append the one byte checksum to a command
    #returns the complete byte array
    def appendChecksum(self, buff):
        buff.append(self.calculateChecksum(buff))
        return buff


def send_server(data, host):
        sock=socket(AF_INET,SOCK_STREAM)
        sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        sock.setblocking(0)
        sock.settimeout(3)
        sock.connect((host, 1000))
        sock.sendall(data)
        print 'Sent Data'
        print 'Waiting for return data'
        result = sock.recv(1024)

        sock.close()
        return result


def main():
    c = CommUtilities()
    host = "172.16.2.52"
    while True:
        try:
            #Connect to server and send data
            print 'Requesting Board Temp'
            data = c.appendChecksum(getBoardTemp)
            """ The checksum should have appended a 0B byte into the array
            """
            data = bytearray(data)
            print data
            print'sending "%s"' % data
            """  The sending "%s" is where I noticed extra nulls being appedned
            on each pass.  They accumulate as the application keeps running.
            """
            received = send_server(data, host)
            """ I have yet to receive any return data, other than the ACK
            packets from the device.  So I am assuming my data I am sending is wrong.
            """
        except Exception, e:
            print >>sys.stderr, 'send/receive error '.format(e)
            received = e
        finally:
            print "received: ".format(received)

        time.sleep(2)

if __name__ == '__main__':
    main()

提前感谢您的帮助!

【问题讨论】:

【参考方案1】:

问题是CommUtilities.appendChecksum() 修改了它的buff 参数的内容(并且在第一次迭代之后,它计算的校验和为零)。你可以通过简单地先复制来解决这个问题:

    def appendChecksum(self, buff):
        buff = buff[:]  # make copy
        buff.append(self.calculateChecksum(buff))
        return buff

我不确定,但这也可以回答您的第二个问题。

【讨论】:

优秀。这解决了第一个问题。谢谢你。但第二个问题我仍然很开心。 我发送数据,却一无所获。校验和是正确的,但我是否正确地形成了数据包? 我将您的标记为已回答。我使用了wireshark,我得到了正确的数据有效负载。只是没有得到设备的响应。现在必须是介于两者之间的东西......但是什么?!?!?!啊。我希望最终能弄清楚。 也许你可以设置一个测试服务器来帮助确定问题出在哪里,如this问题所示。【参考方案2】:

appendChecksum 总是将一个字节附加到代码中的输入参数 getBoardTemp。我不明白你为什么说“校验和应该在数组中附加一个 0B 字节”。

【讨论】:

对字节数组使用 XOR 得出的值应该是 0x0B。对于那个数组,它应该总是这样。是的,但是在它运行一次后我一直在填充。 martineau 的解决方案有助于解决这个问题。但是关于我是否正确地进行数据包形成的部分仍然在逃避我。

以上是关于使用校验和将字节数组转换为字符串。在 python 中重新迭代时获取额外的空字节的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Python 中将字符串转换为字节数组

在 Python 3 中将二进制字符串转换为字节数组

python3:字节与字节数组,并转换为字符串和从字符串转换

将字符串的python列表转换为字节数组

Python - 将字节数组转换为 JSON 格式

Golang 字节数组 - 获取校验和