0

我正在编写一个小应用程序,它本质上是在 SOAP 中来回交换 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 无论如何都不应受到责备,因为在模拟器上执行很好。请注意,0atmaxLength表示“无限”缓冲区。

有谁知道是什么原因造成的?

4

3 回答 3

2

1426 听起来很像 MTU(Maximum Transmit Unit),即你可以发送的最大 TCP 数据的大小。在不同的网络媒体和不同的配置上它的大小不同,但 1426 是很常见的。

这表明您将 TCP 数据包的接收与 XML 消息的完成混淆了。不能保证 TCP 数据包将在 XML 消息边界上结束。GCDAsyncSocket 是一个低级库,它使用 TCP,而不是 XML。

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

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

于 2012-03-13T02:51:12.877 回答
1

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

[sock readDatawithTimeout:-1 tag:0]

但后来搬到

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

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

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

于 2012-03-15T03:50:03.263 回答
0

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

TCP 是一种基于流的协议。从理论上讲,底层 IP 协议的数据包大小应该没有什么区别,但是如果您读取套接字的速度足够快,您很可能会以 IP 数据包大小的块的形式获取数据,特别是如果 IP 堆栈以某种方式针对内存使用进行了调整(在这里猜测!)。

于 2012-03-13T10:31:42.100 回答