我正在制作一款多人iOS游戏并遇到了以下问题:我发送了一个包含自定义对象数组的字典。这些自定义对象符合NSCoding
。我将字典转换为NSData
,如下所示:
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:packet];
然后发送
[asyncSocket writeData:data withTimeout:-1 tag:tag];
收到
[sock readDataWithTimeout:-1 tag:tag];
尝试取消归档
NSDictionary *dict = [NSKeyedUnarchiver unarchiveObjectWithData:data];
一切看起来都非常简单,但应用程序在取消归档数据时崩溃,我收到以下错误
[NSKeyedUnarchiver initForReadingWithData:]:难以理解的存档(0x62,0x70,0x6c,0x69,0x73,0x74,0x30,0x30)'
我查看了发送和接收数据的描述,发现数据来到接收设备1)已更改并且2)被截断。
当我通过GameKit协议,Game Center和蓝牙发送完全相同的数据时,没有这样的问题 - 我收到数据不变,所以很明显问题出在GCDAsyncSocket深处。
有没有人遇到过这样的麻烦?感谢
答案 0 :(得分:3)
正因如此:The TCP protocol is modeled on the concept of a single continuous stream of unlimited length.您需要向data
某些类型的终结符指示符附加并使用readDataToData方法。或者您需要在data
前加上data
长度的指示符。因此,当您使用readDataWithTimeout时,您可以从传入的TCP流中提取确切的字节数。
如何使用GCDAsynsSocket的作者
的终结符的示例NSString *welcomeMsg = @"Welcome to the AsyncSocket Echo Server\r\n";
NSData *welcomeData = [welcomeMsg dataUsingEncoding:NSUTF8StringEncoding];
[newSocket writeData:welcomeData withTimeout:-1 tag:WELCOME_MSG];
[newSocket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:READ_TIMEOUT tag:0];
您之所以不必使用GameKit完成上述所有操作,是因为GameKit协议会为您完成所有这些操作。