我有一个应用程序设置为使用NSStream
s 通过 TCP 连接在两个 iOS 设备之间发送数据。
发送的数据由两部分组成:
- 一个整数,表示即将到来的消息对象的大小
- 消息对象,一些
NSStrings
和一个NSData
用 NSKeyedArchiver 编码的对象
问题:
- 当 NSData 对象大约为 1.5Mb 时,当我尝试对其进行解码时,我得到一个难以理解的存档异常。当读取消息应该在的位置后面的 4 个字节时,那里是一个大数字,而不是下一条消息的大小。
- 当 NSData 对象大约 80Kb 时,成功解码了两条消息,然后我得到了难以理解的存档异常。
似乎数据在某些时候出现了乱序……尽管 TCP 的全部目的是保持它的有序。所以,一定是我的问题!
相关代码
服务器
sendData:
传递已使用 NSKeyedArchiver 编码的 Message 对象。它被要求在短时间内收到 100 条消息
// dataQueue is an NSMutableArray
- (void) sendData:(NSData *)data
{
int size = data.length;
NSData *msgSize = [NSData dataWithBytes:&size length:sizeof(int)];
if (self.outputStream.hasSpaceAvailable && (self.dataQueue.count == 0)) {
[self.dataQueue addObject:data];
[self.outputStream write:msgSize.bytes maxLength:msgSize.length];
}
else {
[self.dataQueue addObject:msgSize];
[self.dataQueue addObject:data];
}
}
//called by NSStreamDelegate method when space is available
- (void) hasSpaceAvailable
{
if (self.dataQueue.count > 0) {
NSData *tmp = [self.dataQueue objectAtIndex:0];
[self.outputStream write:tmp.bytes maxLength:tmp.length];
[self.dataQueue removeObjectAtIndex:0];
}
}
客户
streamHasBytes:
收集消息片段并将它们附加到 self.buffer。当 self.buffer 的长度大于 self.buffer 前 4 个字节指示的消息长度时,Message 对象被解析...
//Called by NSStreamDelegate method when bytes are available
- (void) streamHasBytes:(NSInputStream *)stream
{
NSInteger bytesRead;
uint8_t buffer[32768];
bytesRead= [stream read:buffer maxLength:sizeof(buffer)];
if (bytesRead == -1 || bytesRead == 0) //...err
@synchronized(self) { //added to test concurrency
[self.buffer appendBytes:buffer length:bytesRead];
}
[self checkForMessage];
}
- (void) checkForMessage
{
@synchronized(self) { //added to test concurrency
int msgLength = *(const int *)self.buffer.bytes;
if (self.buffer.length < msgLength) return;
//remove the integer from self.buffer
[self.buffer replaceBytesInRange:NSMakeRange(0, sizeof(int)) withBytes:NULL length:0];
//copy the actual message from self.buffer
NSData *msgData = [NSData dataWithBytes:self.buffer.bytes length:msgLength];
//remove the message from self.buffer
[self.buffer replaceBytesInRange:NSMakeRange(0, msgLength) withBytes:NULL length:0];
Message *theMsg = [NSKeyedUnarchiver unarchiveObjectWithData:msgData];
[self.delegate didReceiveMessage:theMsg];
}
}
编辑:
我现在注意到,在第一个消息中的 NSData 对象大约为 1.5Mb 的情况下,对于大约 1.6Mb 的总消息大小,客户端仅收到大约 1.3Mb ......这将解释难以理解的存档错误。为什么不能交付所有数据?