【问题标题】:Using ntohl and htonl problems on iPhone在 iPhone 上使用 ntohl 和 htonl 问题
【发布时间】:2014-07-20 11:07:06
【问题描述】:

我创建了一个 NSDATA 对象,然后通过网络发送。我无法从收到的 NSDATA 流中获取正确的值。

这里有一些快速代码可以重现我的问题。无需网络传输。

    NSMutableData *data = [[NSMutableData alloc] initWithCapacity:150];

    // put data in the array
    [data woaAppendInt8:4];
    [data woaAppendInt32:2525];
    [data woaAppendInt8:6];
    [data woaAppendInt32:1616];

    // get data out of array
    size_t offset  = 0;

    int x1 = [data woaInt8AtOffset:offset];
    offset += 1;  // move to next spot
    NSLog(@"Should be 4 = %i",x1);

    int x2 = [data woaInt32AtOffset:offset];
    offset = offset + 4; // Int's are 4 bytes
    NSLog(@"Should be 2525 = %i",x2);

    int x3 = [data woaInt8AtOffset:offset];
    offset += 1;  // move to next spot
    NSLog(@"Should be 6 = %i",x3);

    int x4 = [data woaInt32AtOffset:offset];
    offset = offset + 4; // Int's are 4 bytes
    NSLog(@"Should be 1616 = %i",x4);

我正在使用 NSDATA 类别来简化流程。这是分类代码:

    @implementation NSData (woaAdditions)

- (int)woaInt32AtOffset:(size_t)offset
{
    const int *intBytes = (const int *)[self bytes];
    return  ntohl(intBytes[offset / 4]);
}

- (char)woaInt8AtOffset:(size_t)offset
{
    const char *charBytes = (const char *)[self bytes];
    return charBytes[offset];
}

@end

@implementation NSMutableData (waoAdditions)

- (void)woaAppendInt32:(int)value
{
    value = htonl(value);
    [self appendBytes:&value length:4];
}

- (void)woaAppendInt8:(char)value
{
    [self appendBytes:&value length:1];
}

@end

woaInt8AtOffset 效果很好,可以显示 4 和 6。woaInt32AtOffset 显示一些巨大的数字。

代码有什么问题?

【问题讨论】:

  • 建议 - 在使用具有特定大小的值时,使用更合适的类型。示例 - 对 8 位值使用 uint8_t 而不是 char。对 32 位值使用 uint32_t 而不是 int 等。
  • [self getBytes:&buf range:NSMakeRange(offset, 4)];memcpy() 比尝试自己从字节缓冲区中提取值更有意义。问题是您没有提取正确大小的值,您只是在访问(不正确的)偏移量并认为它会正确提升。
  • 真正的错误在于ntohl(intBytes[offset / 4]);。摆脱分裂。你想要ntohl(intBytes[offset]);
  • 我觉得你们都部分正确。我已按照建议更新了类别以使用 int32_t。还是同样的问题。我注意到,如果我使用所有相同的尺寸(即:所有 32 个值),这可能是 /4 的结果。我不确定如何更新代码以使用 [self getbytes:range] 选项,因为我在尝试时不断遇到访问冲突。
  • 如果伪代码还不够,那么 here's a gist 该方法的工作版本。

标签: ios objective-c htonl


【解决方案1】:

我已更新代码以使用 int32_t 并修改类别如下:

- (int)woaInt32AtOffset:(size_t)offset
{
    int32_t buf;
    [self getBytes:&buf range:NSMakeRange(offset, 4)];
    return ntohl(buf);
}

代码现在可以正常工作。太棒了,谢谢。

【讨论】:

  • 这是正确且可移植的方式。适用于任何处理器,无论是 32 位还是 64 位。如果偏移量是奇数,则没有问题。
猜你喜欢
  • 2016-08-23
  • 2012-07-10
  • 2019-07-23
  • 1970-01-01
  • 2013-03-29
  • 1970-01-01
  • 1970-01-01
  • 2017-02-05
  • 1970-01-01
相关资源
最近更新 更多