首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CocoaAsyncSocket和从套接字读取数据

CocoaAsyncSocket和从套接字读取数据
EN

Stack Overflow用户
提问于 2011-07-22 09:47:43
回答 1查看 3.6K关注 0票数 5

在基于TCP套接字的服务器上,我通过流发送数据包,其中数据包由指定数据包中字节数的报头组成,后跟该字节数。对于那些熟悉Erlang的人,我简单地设置了{packet,4}选项。在iOS端,假设我想要计算出此消息的流大小,我的代码如下所示:

代码语言:javascript
复制
[asyncSocket readDataToLength:4 withTimeout:-1 tag:HEADER_TAG];

这样就可以很好地工作,并调用下面的委托方法回调:

代码语言:javascript
复制
onSocket:didReadData:withTag:

我认为下一个合乎逻辑的步骤是找出流的大小,我使用以下命令来实现:

代码语言:javascript
复制
  UInt32 readLength;
  [data getBytes:&readLength length:4];
  readLength = ntohl(readLength);

在服务器端硬编码了12个字节的字符串之后,readLength确实也在客户端读取了12个字节,所以到目前为止一切正常。我从以下几个方面着手:

代码语言:javascript
复制
 [sock readDataToLength:readLength withTimeout:1 tag:MESSAGE_TAG];

但是,此时不再调用回调onSocket:didReadData:withTag:。取而代之的是读取超时,可能是因为我没有正确处理读取,调用了这个委托方法:

代码语言:javascript
复制
- (NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length 

因此,服务器总共发送了16字节、4字节的报头和12字节的二进制流。

我确信错误出在我使用CocoaAsyncSocket的方式上。在我弄清楚流的大小之后,如何正确地读取流的其余部分?

**更新**

我改变了我的客户端,现在它似乎起作用了。问题是,我不明白readDataToLength在新解决方案中的意义。以下是我将最初的阅读更改为:

代码语言:javascript
复制
[socket readDataWithTimeout:-1 tag:HEADER_TAG];

现在,在我的回调中,我只需执行以下操作:

代码语言:javascript
复制
- (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有什么意义呢?没有办法在客户端预先知道消息的长度,那么在什么情况下使用该方法是一个好的用例呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-07-22 15:42:58

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

我猜数据是到目前为止从套接字读取的总累积数据。如果该数据包含您的整个数据包,则没有问题。但是,如果不是这样,您可能希望继续使用readDataToLength对剩余数据执行套接字的阻塞读取。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6784872

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档