通过NSStream在iOS设备之间发送后解析数据 [英] Parsing data after sending between iOS devices over NSStream

查看:266
本文介绍了通过NSStream在iOS设备之间发送后解析数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我设置了一个应用程序,用于通过TCP连接使用NSStream在两个iOS设备之间发送数据.

I have an application set up to send data between two iOS devices using NSStreams over a TCP connection.

发送的数据包括两个部分:

The data sent consists of two parts:

  1. 一个整数,指示要传入的消息对象的大小
  2. 消息对象,一些NSStrings和使用NSKeyedArchiver编码的NSData对象
  1. An integer indicating the size of the message object to come
  2. The message object, some NSStrings and an NSData object encoded with NSKeyedArchiver

问题:

  1. 当NSData对象大约为1.5Mb时,在尝试对其进行解码时会遇到无法理解的存档异常.当读取该消息应在的后面的4个字节时,此处存在大量字节,而不是下一条消息的大小.
  2. 当NSData对象大约为80Kb时,两条消息被成功解码,然后我得到了无法理解的存档异常.

似乎在某些时候数据混乱了……尽管TCP的全部目的是使数据保持秩序.所以,我一定是问题所在!

It seems like the data is getting out of order at some point... though the whole purpose of TCP is to keep it in order. So, I must be the problem!

sendData:将传递已使用NSKeyedArchiver编码的Message对象.它在短时间内被要求发送100条消息

sendData: is passed the Message object that has been encoded with an NSKeyedArchiver. It is called for 100ish messages in a short period of time

// 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对象...

Client

streamHasBytes: collects the message fragments and appends them to self.buffer. When the length of self.buffer becomes greater than the message length indicated in the first 4 bytes of self.buffer, the Message object is parsed...

//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的消息...解释难以理解的存档错误.为什么所有数据都无法传递?

I'm now noticing that, in the case where the NSData object in the first Message is around 1.5Mb, for a total Message size of about 1.6Mb, only about 1.3Mb are received by the client... This would explain the incomprehensible archive errors. Why would all of the data not be delivered?

推荐答案

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

It turns out that in some cases only a fraction of the data that I assumed was sending was actually sending. NSOutputStream's write:maxLength: method returns the number of bytes that were actually written to the stream. So the hasSpaceAvailable method above can be fixed with

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

这篇关于通过NSStream在iOS设备之间发送后解析数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆