刷新 Twisted 的写缓冲区

Flushing Twisted's write buffer

Twisted 的 Connection class 从抽象 class FileDescriptor 继承了 write 方法。如您所见here,class有一个缓冲区,直到缓冲字节总数大于bufferSize(class中的属性FileDescriptor).

对于我的特定需求,我想尽快将数据写入套接字,因此我想避免在传输的任何时候缓冲它们。我已将 TCP_NODELAY 设置到套接字,但数据仍在 Twisted 的 write 调用中缓冲。

因此,我解决此问题的方法是调用 FileDescriptor.doWrite 方法,该方法将尝试在缓冲区中写入任何数据(请参阅 source)。我总是在 write 之后调用 doWrite,如下所示:

...
self.transport.write(data)
self.transport.doWrite()
...

解决方法似乎工作正常,但有时会出现以下错误:

    self.transport.doWrite()  # Flush twisted buffer
File "/usr/local/lib/python2.7/dist-packages/Twisted-14.0.2-py2.7-linux-x86_64.egg/twisted/internet/abstract.py", line 270, in doWrite
    self.stopWriting()
File "/usr/local/lib/python2.7/dist-packages/Twisted-14.0.2-py2.7-linux-x86_64.egg/twisted/internet/abstract.py", line 429, in stopWriting
    self.reactor.removeWriter(self)
File "/usr/local/lib/python2.7/dist-packages/Twisted-14.0.2-py2.7-linux-x86_64.egg/twisted/internet/epollreactor.py", line 344, in removeWriter
    EPOLLOUT, EPOLLIN)
File "/usr/local/lib/python2.7/dist-packages/Twisted-14.0.2-py2.7-linux-x86_64.egg/twisted/internet/epollreactor.py", line 322, in _remove
   primary.remove(fd)
KeyError: 11

问题是 doWrite 调用 stopWriting,它试图从 reactor 中的作者列表 remove 本身(Connection 对象) .引发异常是因为它无法在列表中找到该对象。

这很奇怪,因为 write 应该注册 reader 以防 data 参数不是 None(我认为问题是数据有时是 None,所以我在数据存在的情况下包含了 write & doWrite)。所以,我决定只捕获 KeyError 异常并忽略它,如下所示:

...
if data:
    self.transport.write(data)
    try:
        self.transport.doWrite()
    except KeyError:
        pass
...

然而,异常不断弹出,甚至关闭了 TCP 连接。

现在我在 doWrite 中捕获了异常,但我不知道在何处以及为何引发异常。另外,我不知道这个 hack 的副作用是什么。可能是我过度简化了整个 Twisted 的文件描述符范例(我还不够了解)。我也不知道这是否是实际预期的行为,在任何情况下,Twisted 都不应该在将元素从列表中删除之前检查该元素是否在作者列表中?

doWrite 不在,您可以打电话。它是运输工具和反应器之间的接口的一部分。它不是传输和协议之间的接口的一部分。

FileDescriptor 在写入一定数量的字节之前不会缓冲写入。它只会缓冲写入(最多),直到反应器有机会再次 运行 。 Twisted 是一个协作式多任务系统。一次只发生一件事。如果发生的一件事是您的应用程序代码 运行ning,那么反应器就不会处理它的工作(比如将字节写入文件描述符)。每件事都必须等待另一件事完成才能开始。

无论是什么导致您得出基于大小的写入缓冲区的结论都是错误的。无论您要解决什么问题,解决方案都不是这样的。