Rya*_*anM 0 network-programming objective-c nsstream nscoder ios5
好的,所以我整天都在这个bug,我想我已经把它缩小到了根本问题.
我正在开发一个应用程序,它要求我编写自己的版本,NSNetService并NSNetServiceBrowser允许在iOS 5中通过蓝牙使用Bonjour.这是一次伟大的冒险,因为在我开始这个项目之前我对网络编程一无所知.我从各种示例项目和经典的Unix网络编程教科书中学到了很多东西.我的实现主要基于Apple的DNSSDObjects示例项目.我已经添加了代码,以便在服务解决后实际建立设备之间的连接.一个NSInputStream和一个NSOutputStream是通过CFStreamCreatePairWithSocketToHost( ... ).
我试图通过此连接发送一些数据.数据由一个整数,一些NSStrings和一个NSData存档的对象组成NSKeyedArchiver.大小NSData约为150kb,因此整个消息的大小约为160kb.通过连接发送数据后,当我尝试取消归档时,我收到以下异常...
Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '*** -[NSKeyedUnarchiver initForReadingWithData:]: incomprehensible archive
Run Code Online (Sandbox Code Playgroud)
经过进一步探索后,我注意到收到的数据只有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..");
}
}
}
Run Code Online (Sandbox Code Playgroud)
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;
}
}
Run Code Online (Sandbox Code Playgroud)
用于处理流事件的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*/
}
}
Run Code Online (Sandbox Code Playgroud)
NSStream像这样的网络将使用TCP连接.它可以变化,但最大数据包大小通常约为2k.由于您发送的消息实际上是160k,因此它将被分成多个数据包.
TCP将此抽象为仅仅是一个数据流,因此您可以确保所有这些数据包将以正确的顺序接收.
但是,stream:handleEvent:当只有前2k的数据到达时,可能正在调用委托方法 - 它没有办法知道在它发生之前会有更多的数据到来.
请注意,该方法read:maxLength:不会让您总是获得最大长度 - 在这种情况下,它似乎只给您高达2k.
您应该计算实际值bytesReceived,并将所有数据连接在一起,直到您收到等待的总金额.
接收器如何知道它想要多少数据? - 您可能希望在发送数据之前设计协议,然后发送一个定义大小的整数,指示即将到来的数据的长度.或者,如果您只是通过套接字发送一条消息,则可以在完成后关闭它,并在套接字关闭后仅使接收器取消归档.
| 归档时间: |
|
| 查看次数: |
2189 次 |
| 最近记录: |