用struct模块实现python so

发布时间:2019-09-08 09:10:20编辑:auto阅读(1521)

    最近跳槽到西安一家机器人公司,我们的产品属于教育机器人的范畴,为了增强客户吸引力,引进了一个智能家居公司的产品API接口,让机器人来操作智能家居


    该公司的智能家居API是自定义TCP包,即直接在TCP头后面写自定义数据结构:

    客户端请求下载 家具数据库 的格式

    命令字(4字节,小端)

    0x4c

    服务器返回请求结果 的格式

    命令字(4字节,小端) payload长度(4字节,小端) payload(N*1字节)
    0x43 11262(尺寸很大) sqlite数据库


    默认python socket只能收发字符串,需要借助struct才能收发二进制数据


    发送请求

    cmd_word = 0x4c
    tx_buf = struct.pack('<I', cmd_word)
    sock.sendall(tx_buf)

    tx_buf据struct的文档说是其对输入编码生成的字符串,用type(tx_buf)显示确实是<type 'str'>,print tx_buf显示字母L

    但len(tx_buf) == 4, print repr(tx_buf)显示

    'L\x00\x00\x00'

    也就是说len('L\x00\x00\x00') == 4

    对于从C语言转过来的人来说,上面情况真是理解不能,但它就是发送成功了


    接收应答

    fp = open('house.db', 'wb+')
    recv_cnt = 0
    while True:
        rx_buf = sock.recv(4096)
        len_buf = len(rx_buf)
        if len_buf ==0:
            break
        if recv_cnt == 0:
            cmd_word, data_len_total = struct.unpack(rx_buf[0:8])
            buf = buffer(rx_buf, 8, len_buf - 8)
            fp.write(buf)
        else:
            buf = buffer(rx_buf)
            fp.write(buf)
        recv_cnt = recv_cnt +1

    注意:

    0、接收自定义帧头时用unpack,可以获得结构体各字段取值

    1、接收自定义帧内容(字节流)时不用unpack,因为unpack返回的是tuple,而write不支持tuple类型

    2、因为是二进制写入,所以必须将str转成buffer类型

    3、二进制数据很大时,底层会拆分成多个以太网帧,如果你sendall后马上recv,则可能只收到1448字节,不要担心,这是因为你recv时内核协议栈只有一帧这么多数据,它全部返回给你了,满足socket编程的标准






    

关键字