1

我正在阅读有关如何将 NSData 用于网络消息的示例。

创建 NSData 时,该示例使用:

unsigned int state = htonl(_state);
[data appendBytes:&state length:sizeof(state)];

将 NSData 转换回来时,该示例使用:

  [data getBytes:buffer range:NSMakeRange(offset, sizeof(unsigned int))];
  _state = ntohl((unsigned int)buffer);

在这个例子中是不是没有必要使用 htonl 和 ntohl ? - 由于数据是在 iOS 设备上打包/解包的,字节顺序不会相同,因此不需要使用 htonl 和 ntohl。-使用方式不正确吗?该示例使用 htonl 进行打包,使用 ntohl 进行解包。但实际上,如果知道发送者或接收者正在使用特定格式,难道不应该只这样做吗?

4

1 回答 1

3

该示例使用 htonl 进行打包,使用 ntohl 进行解包。

这是对的。

当发送者通过网络传输数据(整数、浮点数)时,它应该将它们重新排序为“网络字节顺序”。接收器通过从网络字节顺序重新排序为“主机字节顺序”来执行解码。

但实际上,如果知道发送者或接收者正在使用特定格式,难道不应该只这样做吗?

通常,发送方不知道接收方的字节顺序,反之亦然。因此,为了避免歧义,需要定义“网络”的字节顺序。如果发送者和接收者确实为网络正确编码/解码,这很好用。

编辑:

如果您担心编码的性能:

在现代 CPU 上,字节交换所需的机器代码非常快。

在语言级别上,编码和解码一系列字节的函数也可以非常快。不过,我们帖子中的 Objective-C 示例不属于那些“快速”的例程。

例如,由于主机字节顺序在编译时是已知的,ntohl如果主机字节顺序等于网络字节顺序,则成为“空”函数(又名“NoOp”)。

其他字节交换实用程序函数在ntoh64 位、双精度和浮点值的宏系列上扩展,可以利用 C++ 模板技巧,这些技巧也可能成为“NoOp”函数。

然后可以将这些“空”函数完全优化掉,这有效地导致机器代码只执行move从源缓冲区到目标缓冲区的操作。

然而,由于字节交换的额外开销非常小,这些在不需要交换的情况下的优化只能在高性能代码中感知。但你的第一句话:

[data getBytes:buffer range:NSMakeRange(offset, sizeof(unsigned int))];

比下面的语句贵得多

_state = ntohl((unsigned int)buffer);

即使需要字节交换。

于 2013-11-21T08:20:08.687 回答