2

我正在将CocoaAsyncSocket用于 iOS 项目。我正在尝试通过异步接口读取VarInts 。这个问题与字符串之类的其他东西不同,我可以在其中添加一个长度前缀,但我事先不知道 varint 的长度。它需要一次处理一个字节,但由于每个读取操作都是异步的,其他读取调用可能已在其间排队。

我考虑读入一个缓冲区然后处理它,比如读取 5 个字节(varint-32 的最大长度),然后将额外的字节推回,但如果 varint 只有 4 个字节并且我正在等待一个第 5 个字节可用。

我怎样才能做到这一点?此外,我无法更改另一端的协议以使用固定大小的整数。


这是 Josh 要求的代码片段

- (void)readByte:(void (^)(int8_t))onComplete {
    NSUInteger size = 1;
    int32_t tag = OSAtomicAdd32(1, &_nextTag);
    dispatch_async(self.dispatchQueue, ^{
        [self.onCompleteHandlers setObject:(^void (NSData* data) {
            int8_t x = 0;
            [data getBytes:&x length:size];
            onComplete(x);
        }) forKey:[NSNumber numberWithInteger:((NSInteger) tag)]];
        [self.socket readDataToLength:size withTimeout:-1 tag:tag];
    });
}

回调保存在字典中,用于委托方法socket: didReadData: withTag

假设我正在逐字节读取 VarInt:

  • 执行读取 varint 的第一个字节
  • 不知道我们是否需要为 varint 读取另一个字节;这取决于第一次读取的结果
  • (可能)为其他内容读取另一个字节
  • 读取 varint 的第二个字节,但现在实际上是读取的第三个字节

我可以想象使用一个标志来指示我是否处于多部分读取中,并使用一个队列来保存应该在多部分读取之后执行的读取,并且我已经开始编写它,但是它非常混乱。只是想知道是否有标准/推荐/更好的方法来解决这个问题。

4

1 回答 1

1

简而言之,有 4 种方法可以知道从套接字读取多少...

  1. 读取一些格式,您可以从Content-Length标题中推断出长度......只有在发送正文之前可以将整个请求放在一起时才有效。
  2. 读到某种模式:就像\r\n\r\n在标题的末尾
  3. 读取直到超时......在 n 秒后没有得到任何字节后,您刷新缓冲区并关闭连接。
  4. 阅读直到服务器关闭连接......实际上曾经很常见。

这些都有问题,在你的情况下,我可能会倾向于使用一些现有的协议。

当然这样做有开销,你可能会发现你不想使用任何应用程序级别的东西,你的请求可能像:

client>"doMath(2+5)\0"

server>"(7)\0"

但很难具体回答您的一般性问题。

编辑:

因此,我进一步研究了 varint base-128 问题,我认为实际上只有超时或关闭连接的服务器才会起作用,如果您在 TCP 级别编写这些内容,这太可怕了......

于 2014-01-03T01:17:47.493 回答