Objective c iOS数据包长度

Objective c iOS数据包长度,objective-c,ios,kissxml,gcdasyncsocket,Objective C,Ios,Kissxml,Gcdasyncsocket,我正在编写一个小应用程序,它本质上是在a-la-SOAP之间来回交换XML。我有一个基于OSX的服务器和一个iPad客户端。我在客户机上使用KissXML,在服务器上使用内置的XML解析器。我在两者上使用GCDAsyncSocket进行通信 当我在iPad模拟器上测试我的应用程序时,完整的XML就会出现。一切正常 然而,当我使用我的开发设备(实际的物理iPad)时,其他一切都可以正常工作,但XML在1426个字符后终止。我已验证此错误发生在多台iPad上 当我订阅GCDAsyncSocket上的

我正在编写一个小应用程序,它本质上是在a-la-SOAP之间来回交换XML。我有一个基于OSX的服务器和一个iPad客户端。我在客户机上使用
KissXML
,在服务器上使用内置的XML解析器。我在两者上使用
GCDAsyncSocket
进行通信

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

然而,当我使用我的开发设备(实际的物理iPad)时,其他一切都可以正常工作,但XML在1426个字符后终止。我已验证此错误发生在多台iPad上

当我订阅
GCDAsyncSocket
上的传入数据包时,我使用
[sock readDataWithTimeout:-1
缓冲区:[NSMutableData新建]
缓冲偏移量:0
最大长度:0
标签:0]和之前的一个简单的
[sock readDataWithTimeout:-1标记:0]但两者的结果相同。看来GCDAsyncSocket无论如何都不是罪魁祸首,因为模拟器上的执行情况良好。请注意,
maxLength
处的
0
表示“无限”缓冲区


有人知道是什么导致了这种情况吗?

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

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

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


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

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

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

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


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

在查看了
GCDAsyncSocket
的代码后,我想说完全有可能它有一个bug。例如,如果您正在读取一个安全套接字,那么在iPhone上使用cfsocket机制而不是普通的Unix样式的文件描述符,并且作者可能对套接字何时关闭做出了无效的假设。既然您已经有了源代码,我将尝试使用调试器逐步检查它,以查看是否过早地标记了文件结尾


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

查看了
GCDAsyncSocket
的代码后,我想说这里面完全有可能有个bug。例如,如果您正在读取一个安全套接字,那么在iPhone上使用cfsocket机制而不是普通的Unix样式的文件描述符,并且作者可能对套接字何时关闭做出了无效的假设。既然您已经有了源代码,我将尝试使用调试器逐步检查它,以查看是否过早地标记了文件结尾


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

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

[sock readDatawithTimeout:-1标记:0]

但是后来搬到了

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

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

关于这个解决方案还有一点需要注意:因为我使用的是类似SOAP的协议,所以空格不是问题。但是,如果您的用户对终止空白行很敏感,您可以使用类似于
[incomingdecodeddnsstringmessagestringbytrimmingcharactersinset:[NSCharacter]的方法