2011-07-22 104 views
5

在我的基于TCP套接字的服务器上,我通过流发送数据包,其中数据包由一个标头指定数据包中的字节数,然后是该字节数。对于那些熟悉Erlang的人,我只需设置{packet,4}选项。在iOS方面,我有一些代码看起来是这样的,假设我想找出流的大小此消息:CocoaAsyncSocket和从套接字读取数据

[asyncSocket readDataToLength:4 withTimeout:-1 tag:HEADER_TAG]; 

这工作正常及以下的委托方法调用回调函数:

onSocket:didReadData:withTag: 

我图下一逻辑步骤是找出流的大小,以及我做到这一点与:

UInt32 readLength; 
    [data getBytes:&readLength length:4]; 
    readLength = ntohl(readLength); 

后硬编码的在服务器侧12个字节的串,读数长度确实我ndeed在客户端也读了12,所以迄今为止都是很好的。我继续执行以下:

[sock readDataToLength:readLength withTimeout:1 tag:MESSAGE_TAG]; 

此时虽然回调onSocket:didReadData:withTag:不再调用。相反超时在读正在发生,可能是因为我没有处理的正确读取,此委托方法被调用:

- (NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length 

所以在总体上,服务器发送16个字节,4字节的报头和12字节二进制流。

我相信这个错误是关于我如何使用CocoaAsyncSocket。在了解其尺寸后,阅读其余部分流程的正确方法是什么?

**更新**

我改变了我的客户,它似乎现在工作。问题是,我不明白新解决方案的readDataToLength的意义。这是我改变了我最初的念想:

[socket readDataWithTimeout:-1 tag:HEADER_TAG]; 

现在,在我的回调,我只是做到以下几点:

- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag { 
    if (tag == HEADER_TAG) { 
     UInt32 readLength; 
     [data getBytes:&readLength length:4]; 
     readLength = ntohl(readLength); 
     int offset = 4; 
     NSRange range = NSMakeRange(offset, readLength); 
     char buffer[readLength]; 
     [data getBytes:&buffer range:range]; 
     NSLog(@"buffer %s", buffer); 
     //[sock readDataToLength:readLength withTimeout:1 tag:MESSAGE_TAG]; 
    } else if (tag == MESSAGE_TAG) { 
     //[sock readDataToLength:4 withTimeout:1 tag:HEADER_TAG]; 
    } 

} 

所以一切都进来为一体,有效载荷原子。也许这是因为Erlang {packet,4}的工作原理。我希望是。否则,readDataToLength有什么意义?没有办法在客户端事先知道消息的长度,那么使用该方法的好用例是什么?

回答

1

这取决于你如何从Erlang方面发送,我想。选项{packet, 4}将发送每个数据包,其前缀为4个字节。 Erlang中的每个发送操作都将导致一个数据包以其长度为前缀进行发送(最大长度为4,例如,为2 Gb)。 Erlang文档的相关部分用于setting the socket options using inet:setopts/2

我猜数据是从目前从套接字读取的总累计数据。如果这些数据包含您的整个数据包,那就没问题。但是,如果没有,您可能希望继续使用readDataToLength和其余数据从套接字进行阻塞读取。