gpt4 book ai didi

objective-c - 通过 NSStream 在 iOS 设备之间发送后解析数据

转载 作者:可可西里 更新时间:2023-11-01 02:34:04 24 4
gpt4 key购买 nike

我有一个应用程序设置为通过 TCP 连接使用 NSStream 在两个 iOS 设备之间发送数据。

发送的数据由两部分组成:

  1. 一个整数,表示即将到来的消息对象的大小
  2. 消息对象,一些 NSStrings 和一个用 NSKeyedArchiver 编码的 NSData 对象

问题:

  1. 当 NSData 对象大约为 1.5Mb 时,我在尝试对其进行解码时遇到无法理解的存档异常。当读取消息所在位置之后的 4 个字节时,那里有一个很大的数字,而不是下一条消息的大小。
  2. 当 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...这将解释难以理解的存档错误。为什么所有数据都没有交付?

最佳答案

事实证明,在某些情况下,我假设发送的数据中只有一小部分实际发送了。 NSOutputStreamwrite:maxLength: 方法返回实际写入流的字节数。所以上面的 hasSpaceAvailable 方法可以用

修复
NSInteger i = [self.outputStream write:tmp.bytes maxLength:tmp.length];
if (i < tmp.length) {
//send the difference
}

关于objective-c - 通过 NSStream 在 iOS 设备之间发送后解析数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11528977/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com