首先,NSNumber *numero 是“一个指向 NSNumber 类型的指针”,而 NSNumber 类型是一个 Objective-C 对象。一般来说,除非在文档中特别说明,否则面向对象编程的经验法则是“对象如何选择表示其内部状态的内部细节对于对象实现来说是私有的,应该被视为黑色盒子。”同样,除非文档说明您可以这样做,否则您不能假设 NSNumber 使用 C 原始类型 int 来存储您给它的 int 值。
以下是您appendBytes:numero 时“幕后”发生的事情的粗略估计:
typedef struct {
Class isa;
double dbl;
long long ll;
} NSNumber;
NSNumber *numero = malloc(sizeof(NSNumber));
memset(numero, 0, sizeof(NSNumber));
numero->isa = objc_getClass("NSNumber");
void *bytes = malloc(1024);
memcpy(bytes, numero, sizeof(numero)); // sizeof(numero) == sizeof(void *)
这更清楚地表明,您附加到 NSMutableData 对象 data 的内容是 numero 指向的内容的前四个字节(对于 Obj-C 中的对象,总是isa,对象类)。我怀疑您“想要”做的是将指针复制到实例化对象(numero 的值),在这种情况下您应该使用&numero。如果您使用 GC,因为 NSMutableData 使用的缓冲区未被扫描(即,GC 系统将不再“看到”对象并回收它,这几乎是随机崩溃的保证),这是一个问题稍后一点。)
希望很明显,即使您将指向实例化的NSNumber 对象的指针放入data,该指针也仅在创建它的进程的上下文中才有意义。如果您将该指针发送到另一台计算机,那么指向该对象的指针就更没有意义了——接收计算机没有(实际的、微不足道的)方法来读取指针指向的发送计算机中的内存。
由于您似乎在这部分过程中遇到了问题,所以让我提出一个建议,它将为您节省无数时间来调试一些您一定会遇到的极其困难的实现错误:
放弃尝试在机器之间发送原始二进制数据的整个想法,而只在它们之间发送简单的 ASCII/UTF-8 格式信息。
如果您认为这会很慢或效率低下,那么我建议您首先使用简化的 ASCII/UTF-8 字符串化版本来启动所有内容。相信我,调试原始二进制数据并不好玩,当您调试不可避免的问题时,仅使用NSLog(@"I got: %@", dataString) 的能力是物超所值的。然后,一旦一切都已经凝固,并且您确信您不需要对需要交换的内容进行任何更改,“移植”(因为没有更好的词)该实现到仅二进制版本如果,且仅当,使用 Shark.app 进行分析将其识别为问题区域。作为参考,这些天我可以scp 机器之间的文件,并通过传输使千兆链接饱和。 scp 在传输 80MB/秒的同时,压缩和加密数据的每个字节的处理量可能比这种简单的字符串化要多五千倍。然而,在现代硬件上,这几乎不足以让我的菜单栏中运行的 CPU 计量器发生变化。