如何在Objective-C中读取struct.pack编码的字符串?

时间:2014-12-22 21:46:31

标签: python ios objective-c sockets

我有一个Python服务器,使用struct.pack函数将数据作为字节发送到客户端。数据构造为struct.pack("!bhhh", 0x1, x, y, z)

如何在Objecive-C中回读客户端的所有参数?

我现在使用以下代码: NSString *command = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding]; 得到一个结果 ÿÿÿø

2 个答案:

答案 0 :(得分:0)

这不是字符串数据。不要使用NSString。

您需要定义具有等效布局的结构。这有点棘手,因为您使用的结构奇怪地对齐:

struct __attribute__((__packed__)) {
    uint8_t b;
    uint16_t h1, h2, h3;
} *bhhh = (void *) buffer;

您现在可以将该字段的内容称为bhhh->bbhhh->h1等。

请注意,我使用的名称都是完全虚假的,因为我不知道数据代表什么。不要逐字复制。

答案 1 :(得分:0)

由于您使用的是!前缀,因此数据是以Big Endian编写的。这可以防止您简单地将输入数据类型转换为适当的类型。

因此,您需要使用按位移位计算单词(您的三个h值)。您可以轻松创建宏来简化此操作:

// Read a byte (b) from buf at pos
#define GET_B(buf, pos) (uint8)buf[0]
// Read a (signed) word (H) from buf at pos
#define GET_h(buf, pos) ((int8_t)buf[pos+1] | (int8_t)buf[pos]<<8)
// Read an (unsigned) word (h) from buf at pos
#define GET_H(buf, pos) ((uint8)buf[pos+1] | (uint8)buf[pos]<<8)

使用此示例输入如下所示:

    // created with struct.pack('!bhhh', 1, -200, -300, -400)
    unsigned char input[] = {0x01, 0xff, '8', 0xfe, 0xd4, 0xfe, 'p'};

    NSLog(@"a: %d", GET_B(input, 0));
    NSLog(@"x: %d", GET_h(input, 1));
    NSLog(@"y: %d", GET_h(input, 3));
    NSLog(@"z: %d", GET_h(input, 5));

请注意不同数据类型占用的字节数。 b只是一个字节,但h是两个字节。因此,偏移量为0,1,3和5.