带有nio4r选择循环的Ruby套接字

时间:2013-03-15 06:55:03

标签: ruby sockets asynchronous network-programming asyncsocket

假设我有一个带有一些打开连接的select循环,我将要读取这些连接,并且我有连接到每个连接的状态机,用于解析通过线路传输的一些东西并做正确的事情。因此,假设其中一个连接c已准备就绪,并且select循环将其交给状态机m进行处理。我们想从连接中读取10个字节,我们将使用readpartial。不幸的是,我们只有6个字节,所以m读取6个字节并解除阻塞。下一次循环递给我们c它还有11个字节。 m仍然处于上一次选择循环递给我们c的状态,并且知道它需要再读取4个字节,因此它用readpartial(4)读取这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 == char即使缓冲区中的连接缓冲区超过char

1 个答案:

答案 0 :(得分:1)

像往常一样写出问题我帮助我看到了解决方案。我可以只调用readpartial,而不是在状态机中调用read_nonblock。如果没有什么可读的话,read_nonblock将抛出异常,我可以捕获此异常并取消阻止选择循环。