CocoaAsyncSocket和从套接字读取数据

ran*_*its 5 iphone erlang tcp ios cocoaasyncsocket

在我的基于TCP套接字的服务器上,我通过流发送数据包,其中数据包由指定数据包中字节数的标头组成,后跟该字节数.对于那些熟悉Erlang的人,我只是设置{packet,4}选项.在iOS方面,我的代码看起来像这样,假设我想弄清楚此消息的流的大小:

[asyncSocket readDataToLength:4 withTimeout:-1 tag:HEADER_TAG];
Run Code Online (Sandbox Code Playgroud)

这工作正常,并调用以下委托方法回调:

onSocket:didReadData:withTag:
Run Code Online (Sandbox Code Playgroud)

我认为下一个合乎逻辑的步骤是弄清楚流的大小,我这样做:

  UInt32 readLength;
  [data getBytes:&readLength length:4];
  readLength = ntohl(readLength);
Run Code Online (Sandbox Code Playgroud)

在服务器端硬编码一个12字节的字符串之后,readLength确实在客户端读取了12,所以到目前为止一切都很好.我继续以下内容:

 [sock readDataToLength:readLength withTimeout:1 tag:MESSAGE_TAG];
Run Code Online (Sandbox Code Playgroud)

此时虽然onSocket:didReadData:withTag:不再调用回调.而不是读取超时,可能是因为我没有正确处理读取,这个委托方法被调用:

- (NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length 
Run Code Online (Sandbox Code Playgroud)

所以总的来说,服务器发送16个字节,一个4字节的头和一个12字节的二进制流.

我确信错误在于我如何使用CocoaAsyncSocket.在弄清楚它的大小之后,读取其余流的正确方法是什么?

**更新**

我改变了我的客户,现在似乎正在运作.问题是,我不明白readDataToLength与新解决方案的关系.这是我将我的初始阅读更改为:

[socket readDataWithTimeout:-1 tag:HEADER_TAG];
Run Code Online (Sandbox Code Playgroud)

现在在我的回调中,我只是做以下事情:

- (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];
    }

}
Run Code Online (Sandbox Code Playgroud)

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

Ada*_*erg 1

我想这取决于你如何从 Erlang 端发送。该选项{packet, 4}将发送带有 4 字节长度前缀的每个数据包。Erlang 中的每个发送操作都会导致发送一个带有其长度前缀的数据包(4例如, length 的最大大小为 2 Gb)。Erlang 文档的相关部分是使用设置套接字选项inet:setopts/2

我猜测数据是迄今为止从套接字读取的总累积数据。如果该数据包含您的整个数据包,那就没问题。readDataToLength但如果没有,您可能希望继续使用剩余数据从套接字进行阻塞读取。