从iOS发送C++协议缓冲区消息
问题描述:
在previous Stack Overflow question中,人们在构建我的Akka套接字服务器时向我展示了我的方式错误方面非常有帮助,现在我实际上有一个Akka套接字客户端,它可以发送具有以下帧的消息:从iOS发送C++协议缓冲区消息
消息长度:4个字节 消息类型:4个字节 消息有效载荷:(长度)字节
下面是我使用发送消息iOS的代码:
NSInputStream *inputStream;
NSOutputStream *outputStream;
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"localhost", 9999, &readStream, &writeStream);
inputStream = (__bridge_transfer NSInputStream *)readStream;
outputStream = (__bridge_transfer NSOutputStream *)writeStream;
[inputStream setDelegate:self];
[outputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
// [inputStream open];
[outputStream open];
NSLog(@"NSData raw zombie is %d bytes.", [rawZombie length]);
uint32_t length = (uint32_t)htonl([rawZombie length]);
uint32_t messageType = (uint32_t)htonl(1);
NSLog(@"Protobuf byte size %d", zombieSighting->ByteSize());
[outputStream write:(uint8_t *)&length maxLength:4];
[outputStream write:(uint8_t *)&messageType maxLength:4];
[outputStream write:(uint8_t *)[rawZombie bytes] maxLength:length];
[outputStream close];
的“rawZombie”变量(NSData的*)来自以下的方法:
- (NSData *)getDataForZombie:(kotancode::ZombieSighting *)zombie {
std::string ps = zombie->SerializeAsString();
NSLog(@"raw zombie string:\n[%s]", ps.c_str());
return [NSData dataWithBytes:ps.c_str() length:ps.size()];
}
我看到的症状是,我收到消息,通过iOS的发送,并且它的长度是正确的,因为是消息类型(1),身体碰到罚款。使用Scala protobufs的Akka服务器对消息进行反序列化,并完美地打印出消息中的所有值。问题是,在我收到该消息之后,Akka服务器立即认为它收到了另一条消息(显然,流中有更多数据)。每次运行iOS应用程序时,最后的数据都不一样。
例如,这里是从连续两个消息的一些输出跟踪接收:
received message of length 45 and type 1
name:Kevin
lat: 41.007
long: 21.007
desc:This is a zombie
zombie type:FAST
received message of length 7 and type 4
received message of length 45 and type 1
name:Kevin
lat: 41.007
long: 21.007
desc:This is a zombie
zombie type:FAST
received message of length 164 and type 1544487554
所以你可以看到,右边的阿卡服务器报文接收到正确的数据后,它也接收一些随机任意废话。鉴于我有Akka客户端正常工作没有这种额外的任意废话,我假设有什么问题,我怎么写protobuf对象到NSStream ......任何人都可以发现我的愚蠢的错误,因为我确信这就是这里正在发生。
答
血腥地狱。我不敢相信我没有看到这一点。在此处的代码行中:
[outputStream write:(uint8_t *)[rawZombie bytes] maxLength:length]
我正在使用值“length”作为要传输的最大字节数。不幸的是,为了准备在网络上传输,这个值已经翻转过了“endian”顺序。我用[rawZombie长度]替换了“长度”,它的功能就像一个魅力。
:(
你登录你*发送的消息*的长度作比较? –
所有的长度和字节计数是45 rawZombie长度]是45上的发送(IOS)侧,其与protobuf对象上的ByteSize()方法相同(返回45)。 –
是坏数据的“长度7”部分,那么?此外:大多数时候我看到过这种情况,它或者与发送MemoryStream的后备缓冲区(而不是修剪后的数据),或者搞乱了网络IO。这里是否有这种情况? –