刷新Twisted的写缓冲区

时间:2015-03-06 12:59:46

标签: python tcp buffer twisted

Twisted的Connection类继承了抽象类write中的FileDescriptor方法。如您所见here,该类有一个缓冲区,在缓冲字节总数大于bufferSize(类FileDescriptor中的属性)之前不会刷新。

根据我的特定需求,我想尽快将数据写入套接字,所以我希望避免在传输的任何时候缓冲它们。我已将TCP_NODELAY设置为套接字,但数据仍在Twisted的write调用中缓冲。

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

...
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调用stopWritingConnectionreactor的作者列表中尝试remove本身(write对象)。异常会引发异常,因为它无法在列表中找到此对象。

这很奇怪,因为data应该注册读者以防None参数不是None(我认为问题是数据有时是write,所以我包括在数据存在的情况下doWrite& KeyError。所以,我决定只抓住... if data: self.transport.write(data) try: self.transport.doWrite() except KeyError: pass ... 异常并忽略它如下:

doWrite

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

我不知道在{{1}}中捕获异常时引发异常的位置和原因。另外,我不知道这个黑客的副作用是什么。可能是因为我过度简化了整个Twisted的文件描述符范例(我还不够了解它)。我也不知道这是否是实际预期的行为,不应该扭曲检查元素是否在编写器列表中,然后在列表中删除它?

1 个答案:

答案 0 :(得分:2)

doWrite您无法拨打电话。它是运输和反应堆之间界面的一部分。它不是传输和协议之间接口的一部分。

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

无论是什么导致你得出结论,基于大小的写缓冲区是一个错误。无论您试图解决什么问题,解决方案都不会像这样。

相关问题