1

假设我有一个选择循环,其中包含一些要读取的打开连接,并且我在每个连接上都附加了状态机,这些状态机旨在解析通过网络传输的一些内容并做正确的事情。因此,假设其中一个连接 ,c已准备好,选择循环将其交给状态机m进行处理。我们想从连接中读取 10 个字节,我们将使用readpartial. 不幸的是,我们只收到了 6 个字节,因此m读取 6 个字节并解除阻塞。下次循环交给我们c时,它还有 11 个字节。m仍然处于上次选择循环交给我们时的任何状态,c并且知道它需要再读取 4 个字节,因此它读取这 4 个字节readpartial(4), 使用现在在其缓冲区中的这 10 个字节进行某种副作用操作并转移到新状态。m仍然保持连接,因此此时它可以解除阻塞循环或开始执行新状态指示的操作,其中一项操作可能涉及readpartial. 在这种情况下,正确的做法是继续处理连接,因为readpartial不会阻塞。但是假设动作顺序是:接收 6 个字节,读取 6 个字节并解除阻塞,接收 4 个字节,读取 4 个字节并做一些事情。在这种情况下,将没有什么可读取的,因此如果状态机决定调用readpartial在连接上,它会阻塞选择循环,这是一种不受欢迎的情况,在这种情况下,正确的做法是让状态机解除阻塞并等待选择循环再次出现。

如果我不想阻塞选择循环并且不想在连接缓冲区中留下字节,那么解决这个问题的正确和有效的方法是什么?我已经查看了 Ruby 的 Socket 和 IO API,但我找不到一种方法可以告诉我是否有要阅读的内容。read_nonblock是通过读取单个字节然后将其放回测试流是否可读的潜在探索途径,但在我的测试中它的行为不符合预期,即即使连接缓冲区的内容char = c.read_nonblock(1); c.ungetc(char); wire_data = c.read_partial(10)超过缓冲。wire_data == charchar

4

1 回答 1

1

像往常一样写下我遇到的问题帮助我找到了解决方案。而不是调用readpartial状态机,我可以调用read_nonblock. read_nonblock如果没有可读取的内容,将引发异常,我可以捕获此异常并取消阻塞选择循环。

于 2013-03-15T07:17:36.303 回答