0

好的,所以我整天都在处理这个错误,我想我已经把它缩小到了根本问题。

背景:

我正在开发一个应用程序,该应用程序要求我编写自己的版本,NSNetServiceNSNetServiceBrowser允许在 iOS 5 中通过蓝牙使用 Bonjour。这是一次很棒的冒险,因为在开始这个项目之前我对网络编程一无所知。我从各种示例项目和经典的Unix 网络编程教科书中学到了很多东西。我的实现主要基于 Apple 的DNSSDObjects示例项目。一旦解决了服务,我添加了代码以实际建立设备之间的连接。AnNSInputStream和 anNSOutputStream是通过 获得的CFStreamCreatePairWithSocketToHost( ... )

问题:

我正在尝试通过此连接发送一些数据。数据由一个整数、几个NSStrings和一个NSData用 存档的对象组成NSKeyedArchiver。的大小NSData约为 150kb,因此整个消息的大小约为 160kb。通过连接发送数据后,当我尝试取消归档时出现以下异常...

Terminating app due to uncaught exception 'NSInvalidArgumentException', 
reason: '*** -[NSKeyedUnarchiver initForReadingWithData:]: incomprehensible archive 

经过进一步探索,我注意到接收到的数据只有 2kb 左右。消息被截断,从而使存档“难以理解”。

可能相关的代码:

将数据发送到所有连接设备的方法

- (void) sendMessageToPeers:(MyMessage *)msg
{
  NSEnumerator *e = [self.peers objectEnumerator];

  //MyMessage conforms to NSCoding, messageAsData getter calls encodeWithCoder:
  NSData *data = msg.messageAsData; 

  Peer *peer;
  while (peer = [e nextObject]) {
    if (![peer sendData:data]) {
      NSLog(@"Could not send data to peer..");
    }
  }
}

Peer 类中实际写入数据的方法NSOutputStream

- (BOOL) sendData:(NSData *)data
{
  if (self.outputStream.hasSpaceAvailable) {
    [self.outputStream write:data.bytes maxLength:data.length];
    return YES;
  }
  else {
    NSLog(@"PEER DIDN'T HAVE SPACE!!!");
    return NO;
  }
}

用于处理流事件(“接收”数据)的 NSStreamDelegate 方法

此代码中的缓冲区大小为 32768 b/c,这就是我从中学到的任何示例代码中的内容。它是任意的吗?我尝试将其更改为 200000,认为问题只是缓冲区太小,但它没有改变任何东西.. 我不认为我完全理解发生了什么。

- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
  switch (eventCode) {

    case NSStreamEventHasBytesAvailable: {
      NSInteger       bytesRead;
      uint8_t         buffer[32768];      // is this the issue?
//    uint8_t         buffer[200000];   //this didn't change anything

      bytesRead = [self.inputStream read:buffer maxLength:sizeof(buffer)];
      if (bytesRead == -1) ...;
      else if (bytesRead == 0) ...;
      else {
        NSData  *data = [NSData dataWithBytes:buffer length:bytesRead];
        [self didReceiveData:data];
      }
    } break;

    /*omitted code for other events*/
  }
}
4

2 回答 2

7

NSStream通过这样的网络将使用 TCP 连接。它可能会有所不同,但最大数据包大小通常在 2k 左右。由于您发送的消息实际上是 160k,因此它将被分成多个数据包。

TCP 将其抽象为数据流,因此您可以确定所有这些数据包都将以正确的顺序接收。

然而,stream:handleEvent:当只有前 2k 的数据到达时,可能会调用委托方法——它无法知道还有更多的数据到达。

请注意,该方法read:maxLength:不能保证您始终获得最大长度 - 在这种情况下,它似乎只给您最多 2k。

您应该计算实际的bytesReceived,并将所有数据连接在一起,直到您收到您正在等待的总金额。

接收方如何知道它需要多少数据?– 您可能想要设计您的协议,因此在发送数据之前,您发送一个定义大小的整数,指示即将到来的数据的长度。或者,如果您只通过套接字发送一条消息,您可以在完成后简单地关闭它,并且仅在套接字关闭后让接收方取消归档。

于 2012-07-11T01:55:08.940 回答
1

You seem to be reading from self.inputStream but the stream passed into your stream:handleEvent: method is called aStream. Are they referencing the same object somehow? Otherwise I'm not sure you're reading the stream that actually has bytes available

于 2012-07-11T01:18:07.683 回答