Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/331.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.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
Python 如何在另一个结构中解包一个C型结构?_Python_Struct_Unpack - Fatal编程技术网

Python 如何在另一个结构中解包一个C型结构?

Python 如何在另一个结构中解包一个C型结构?,python,struct,unpack,Python,Struct,Unpack,我通过套接字接口从用C编写的应用程序(服务器)接收数据。发布的数据具有以下结构。我正在用Python编写的客户端接收数据 struct hdr { int-Id; char-PktType; 内部序号; int-Pktlength; }; 结构trl { 字符消息[16]; 长信息; }; 结构数据 { 字符值[10]; 双重结果; 长计数; 短int-valueid; }; 类型定义结构 { 结构hdr hdr_buf; 结构数据[100]; 结构trl trl_buf; }trx_单位;

我通过套接字接口从用C编写的应用程序(
服务器
)接收数据。发布的数据具有以下结构。我正在用Python编写的客户端接收数据

struct hdr
{
int-Id;
char-PktType;
内部序号;
int-Pktlength;
};
结构trl
{
字符消息[16];
长信息;
};
结构数据
{
字符值[10];
双重结果;
长计数;
短int-valueid;
};
类型定义结构
{
结构hdr hdr_buf;
结构数据[100];
结构trl trl_buf;
}trx_单位;
如何解压缩接收到的数据以访问我的内部数据缓冲区?

库中有您所需的一切。

库中有您所需的一切。

使用库是一种方法。但是,您必须对序列化数据的C程序有更多的了解。考虑<代码> HDR < /代码>结构。如果C程序使用朴素方法发送:

struct hdr header;
send(sd, &hdr, sizeof(header), 0);
然后,客户端无法安全地解释发送给它的字节,因为在结构成员之间插入的填充量不确定。特别是,我希望在
PktType
成员之后有三个字节的填充

发送二进制数据最安全的方法是让服务器和客户端直接序列化字节,以确保没有额外的填充,并明确多字节整数的字节顺序。例如:

/*
 * Send a header over a socket.
 *
 * The header is sent as a stream of packed bytes with
 * integers in "network" byte order.  For example, a
 * header value of:
 *   Id: 0x11223344
 *   PktType: 0xff
 *   SeqNo: 0x55667788
 *   PktLength: 0x99aabbcc
 * 
 * is sent as the following byte stream:
 *   11 22 33 44 ff 55 66 77 88 99 aa bb cc
 */
void
send_header(int sd, struct hdr const* header)
{   /* NO ERROR HANDLING */
    uint32_t num = htonl((uint32_t)header->Id);
    send(sd, &num, sizeof(num), 0);
    send(sd, &header->PktType, sizeof(header->PktType), 0);
    num = htonl((uint32_t)header->SeqNo);
    send(sd, &num, sizeof(num), 0);
    num = htonl((uint32_t)header->PktLength);
    send(sd, &num, sizeof(num), 0);
}
这将确保您的客户可以使用以下模块安全解码:

如果无法修改C代码以修复序列化的不确定性,则必须从流中读取数据,找出C编译器插入填充的位置,并使用填充字节格式字符忽略填充值手动生成匹配的格式字符串

我通常用Python编写一个解码器类,从套接字读取完整的值。在您的情况下,它看起来像:

class PacketReader(object):
    def __init__(self, sd):
        self._socket = sd

    def read_packet(self):
        id_, pkt_type, seq_no, pkt_length = self._read_header()
        data_bufs = [self._read_data_buf() for _ in range(0, 100)]
        message, info = self._read_trl()
        return {'id': id_, 'pkt_type': pkt_type, 'seq_no': seq_no,
                'data_bufs': data_bufs, 'message': message,
                'info': info}

    def _read_header(self):
        """
        Read and unpack a ``hdr`` structure.

        :returns: a :class:`tuple` of the header data values
            in order - *Id*, *PktType*, *SeqNo*, and *PktLength*

        The header is assumed to be packed as 13 bytes with
        integers in network byte order.

        """
        buf = self._socket.read(13)
        # >   Multibyte values in network order
        # I   Id as 32-bit unsigned integer value
        # B   PktType as 8-bit unsigned integer value
        # I   SeqNo as 32-bit unsigned integer value
        # I   PktLength as 32-bit unsigned integer value
        return struct.unpack('>IBII', buf)

    def _read_data_buf(self):
        """
        Read and unpack a single ``data`` structure.

        :returns: a :class:`tuple` of data values in order -
            *value*, *result*, *count*, and *value*

        The data structure is assumed to be packed as 28 bytes
        with integers in network byte order and doubles encoded
        as IEEE 754 binary64 in network byte order.

        """
        buf = self._socket.read(28)  # assumes double is binary64
        # >   Multibyte values in network order
        # 10s value bytes
        # d   result encoded as IEEE 754 binary64 value
        # q   count encoded as a 64-bit signed integer
        # H   valueid as a 16-bit unsigned integer value
        return struct.unpack('>10sdqH', buf)

    def _read_trl(self):
        """
        Read and unpack a ``trl`` structure.

        :returns: a :class:`tuple` of trl values in order -
            *Message* as byte string, *info*

        The structure is assumed to be packed as 24 bytes with
        integers in network byte order.

        """
        buf = self.socket.read(24)
        # >   Multibyte values in network order
        # 16s message bytes
        # q   info encoded as a 64-bit signed value
        return struct.unpack('>16sq', buf)
请注意,这是未经测试的,可能包含语法错误,但这就是我解决问题的方法。

使用该库是一种方法。但是,您必须对序列化数据的C程序有更多的了解。考虑<代码> HDR < /代码>结构。如果C程序使用朴素方法发送:

struct hdr header;
send(sd, &hdr, sizeof(header), 0);
然后,客户端无法安全地解释发送给它的字节,因为在结构成员之间插入的填充量不确定。特别是,我希望在
PktType
成员之后有三个字节的填充

发送二进制数据最安全的方法是让服务器和客户端直接序列化字节,以确保没有额外的填充,并明确多字节整数的字节顺序。例如:

/*
 * Send a header over a socket.
 *
 * The header is sent as a stream of packed bytes with
 * integers in "network" byte order.  For example, a
 * header value of:
 *   Id: 0x11223344
 *   PktType: 0xff
 *   SeqNo: 0x55667788
 *   PktLength: 0x99aabbcc
 * 
 * is sent as the following byte stream:
 *   11 22 33 44 ff 55 66 77 88 99 aa bb cc
 */
void
send_header(int sd, struct hdr const* header)
{   /* NO ERROR HANDLING */
    uint32_t num = htonl((uint32_t)header->Id);
    send(sd, &num, sizeof(num), 0);
    send(sd, &header->PktType, sizeof(header->PktType), 0);
    num = htonl((uint32_t)header->SeqNo);
    send(sd, &num, sizeof(num), 0);
    num = htonl((uint32_t)header->PktLength);
    send(sd, &num, sizeof(num), 0);
}
这将确保您的客户可以使用以下模块安全解码:

如果无法修改C代码以修复序列化的不确定性,则必须从流中读取数据,找出C编译器插入填充的位置,并使用填充字节格式字符忽略填充值手动生成匹配的格式字符串

我通常用Python编写一个解码器类,从套接字读取完整的值。在您的情况下,它看起来像:

class PacketReader(object):
    def __init__(self, sd):
        self._socket = sd

    def read_packet(self):
        id_, pkt_type, seq_no, pkt_length = self._read_header()
        data_bufs = [self._read_data_buf() for _ in range(0, 100)]
        message, info = self._read_trl()
        return {'id': id_, 'pkt_type': pkt_type, 'seq_no': seq_no,
                'data_bufs': data_bufs, 'message': message,
                'info': info}

    def _read_header(self):
        """
        Read and unpack a ``hdr`` structure.

        :returns: a :class:`tuple` of the header data values
            in order - *Id*, *PktType*, *SeqNo*, and *PktLength*

        The header is assumed to be packed as 13 bytes with
        integers in network byte order.

        """
        buf = self._socket.read(13)
        # >   Multibyte values in network order
        # I   Id as 32-bit unsigned integer value
        # B   PktType as 8-bit unsigned integer value
        # I   SeqNo as 32-bit unsigned integer value
        # I   PktLength as 32-bit unsigned integer value
        return struct.unpack('>IBII', buf)

    def _read_data_buf(self):
        """
        Read and unpack a single ``data`` structure.

        :returns: a :class:`tuple` of data values in order -
            *value*, *result*, *count*, and *value*

        The data structure is assumed to be packed as 28 bytes
        with integers in network byte order and doubles encoded
        as IEEE 754 binary64 in network byte order.

        """
        buf = self._socket.read(28)  # assumes double is binary64
        # >   Multibyte values in network order
        # 10s value bytes
        # d   result encoded as IEEE 754 binary64 value
        # q   count encoded as a 64-bit signed integer
        # H   valueid as a 16-bit unsigned integer value
        return struct.unpack('>10sdqH', buf)

    def _read_trl(self):
        """
        Read and unpack a ``trl`` structure.

        :returns: a :class:`tuple` of trl values in order -
            *Message* as byte string, *info*

        The structure is assumed to be packed as 24 bytes with
        integers in network byte order.

        """
        buf = self.socket.read(24)
        # >   Multibyte values in network order
        # 16s message bytes
        # q   info encoded as a 64-bit signed value
        return struct.unpack('>16sq', buf)

请注意,这是未经测试的,可能包含语法错误,但这就是我解决问题的方法。

您是通过套接字接收字节串吗?@egaio是的。我是通过套接字接收字节串。您是通过套接字接收字节串吗?@egaio是的。我是通过套接字接收字节串。@Shawley感谢您的指导。你能详细介绍一下10sdIIH和16sII吗?@Soumajit-我添加了一些注释和文档字符串。我还转换为对64位有符号值使用
q
。我错误地认为它只在本机模式下可用。请参见@Shawley的注释(2),谢谢您的指导。你能详细介绍一下10sdIIH和16sII吗?@Soumajit-我添加了一些注释和文档字符串。我还转换为对64位有符号值使用
q
。我错误地认为它只在本机模式下可用。参见@Equalio的注释(2),谢谢您的建议。我不确定
unpack
@equalio中的结构的格式说明符,谢谢你的建议。我不确定
unpack