2013-03-15 13 views
1

假设我有一个选择循环,打开一些打开的连接,我将读取它,并且每个连接都附加了状态机,用于解析通过线路传递的一些内容,正确的事。假设其中一个连接c已准备就绪,并且选择循环将其交给状态机m进行处理。我们想从连接中读取10个字节,我们将使用readpartial。不幸的是,只有6个字节已经给我们,所以m读取6个字节并取消阻止。下一次循环递给我们c它有11个字节。 m仍处于上次选择循环递给我们的c的任何状态,并且知道它需要再读取4个字节,因此它使用readpartial(4)读取这4个字节,使用现在处于这种状态的那10个字节进行某种副作用操作其缓冲区并转移到新的状态。 m仍持有该连接,因此此时它可以解除阻止环路或开始执行新状态指定的操作,其中一个操作可能涉及readpartial。在这种情况下,正确的做法是继续处理连接,因为readpartial不会阻塞。但假设操作的顺序是:接收6个字节,读取6个字节&解锁,接收4个字节,读取4个字节&做一些事情。在这种情况下,没有什么可以读取的,所以如果状态机已经决定在连接上调用readpartial,那么它将阻塞选择循环,这是不合需要的情况,并且在这种情况下正确的事情将是状态机器解锁并等待选择循环再次出现。用nio4r选择循环的红宝石套接字

如果我不想阻塞选择循环,也不想在连接缓冲区中保留字节,那么解决这个问题的正确和有效的方法是什么?我已经浏览了Ruby的Socket和IO API,并且找不到能够告诉我是否有东西需要读取的方法。​​是一个潜在的探索途径,通过读取单个字节然后将其放回,但在我的测试中它不像预期的那样工作,即char = c.read_nonblock(1); c.ungetc(char); wire_data = c.read_partial(10)结果为wire_data == char,即使连接缓冲区有更多在缓冲区中比char

回答

1

像往常一样写出问题,我帮助我看到了解决方案。我可以拨打​​,而不是在状态机中调用readpartial。​​会抛出一个异常,如果没有什么可读的,我可以抓住这个异常并取消阻止选择循环。