我有一个应用程序设置为在两个 iOS 设备之间发送数据NSStream
通过 TCP 连接。
发送的数据由两部分组成:
- 一个整数,指示即将到来的消息对象的大小
- 消息对象,一些
NSStrings
and an NSData
使用 NSKeyedArchiver 编码的对象
问题:
- 当 NSData 对象大约 1.5Mb 时,当我尝试对其进行解码时,会出现无法理解的存档异常。当读取消息应该所在的位置后面的 4 个字节时,发现有一个很大的数字,而不是下一条消息的大小。
- 当 NSData 对象大约 80Kb 时,两条消息被成功解码,然后我得到了难以理解的存档异常。
数据似乎在某个时刻变得混乱……尽管 TCP 的全部目的是保持数据有序。所以,问题一定是我!
相关代码
Server
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];
}
}
Client
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];
}
}
EDIT:
我现在注意到,在第一个消息中的 NSData 对象约为 1.5Mb 的情况下,对于约 1.6Mb 的总消息大小,客户端仅收到约 1.3Mb...这可以解释难以理解的情况存档错误。为什么所有数据都没有传送?
事实证明,在某些情况下,我认为正在发送的数据中只有一小部分实际上正在发送。NSOutputStream
's write:maxLength:
方法返回实际写入流的字节数。所以hasSpaceAvailable
上面的方法可以通过修复
NSInteger i = [self.outputStream write:tmp.bytes maxLength:tmp.length];
if (i < tmp.length) {
//send the difference
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)