iOS数据包长度

时间:2012-03-12 17:00:05

标签: objective-c ios kissxml gcdasyncsocket

我正在编写一个小应用程序,它基本上来回交换XML。我有一个基于OS X的服务器和一个iPad客户端。我在客户端上使用KissXML,在服务器上使用内置的XML解析器。我在两者上使用GCDAsyncSocket进行沟通。

当我在iPad模拟器上测试我的应用程序时,完整的XML会通过。一切正常。

然而,当我使用我的开发设备(一个真正的物理iPad)时,其他一切工作正常,但XML在第1426个字符后终止。我已经确认在多台iPad上发生此错误。

当我订阅GCDAsyncSocket上的传入数据包时,我使用了 [sock readDataWithTimeout:-1 buffer:[NSMutableData new] bufferOffset:0 maxLength:0 tag:0];以前只是一个简单的[sock readDataWithTimeout:-1 tag:0];但两者都有相同的结果。似乎GCDAsyncSocket无论如何都不应该受到责备,因为模拟器上的执行很好。请注意0处的maxLength表示“无限”缓冲区。

有没有人知道造成这种情况的原因是什么?

3 个答案:

答案 0 :(得分:2)

1426听起来非常像MTU(最大传输单位),它是您可以发送的最大TCP数据的大小。它在不同的网络媒体和不同的配置上有不同的大小,但是1426很常见。

这表明您将TCP数据包的接收与XML消息的完成混淆。无法保证TCP数据包将以XML消息边界结束。 GCDAsyncSocket是一个低级库,可以与TCP进行对话,而不是XML。

当您收到每个数据包时,您有责任将其连接到NSMutableData,然后决定何时有足够的数据处理它。如果您的协议在每条消息之后关闭连接,那么您可以读取直到连接关闭。如果没有,那么你将不得不处理一个事实,即给定的数据包甚至可能包含下一条消息。您必须充分解析数据以确定边界的位置。

顺便说一句,你的Mac很可能有不同的MTU,这就是为什么你可能会在不同的平台上看到不同的行为。

答案 1 :(得分:1)

解决方案是,当未指定时,AsyncSocket查看下一行返回。当数据包终止时,它确实返回该行。我正在使用(sock是我的GCDAsyncSocket对象)

[sock readDatawithTimeout:-1 tag:0]

但后来搬到了

[sock readDataToData:[msgTerm dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0]

其中msgTerm是外部常量NSString,定义为“\ r \ n \ r \ n”,并在客户端和服务器源之间共享。这有效地避免了结束数据包的行返回问题。

关于此解决方案的另一个注意事项:因为我使用的是类似SOAP的协议,所以空格不是问题。但是,如果你的终结空白行很有气质,你可以使用像[incomingDecodedNsstringMessage stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]这样的方法来清理它。

答案 2 :(得分:0)

看了GCDAsyncSocket的代码,我说它完全有可能存在错误。例如,如果您正在阅读安全套接字,则在iPhone上使用cfsocket机制而不是普通的Unix风格文件描述符,并且作者可能会对套接字何时关闭做出无效假设。由于您有源代码,我尝试使用调试器逐步执行它以查看文件末尾是否过早被标记。

TCP是基于流的协议。从理论上讲,底层IP协议的数据包大小应该没什么区别,但是如果你足够快地读取套接字,你可能会把你的数据放在IP数据包大小的块中,特别是如果IP堆栈以某种方式调整内存使用(猜猜在这里!)。