Twisted中的新传输和读取器类型
我正在尝试为Twisted添加一个新的传输方式,这个传输方式可以从一个流中读取数据——可以是像tail -f
那样读取文件,或者从管道中读取,但我在Twisted的架构上遇到了一些问题。
我已经准备好了传输部分(实现了ITransport
),它可以处理所有文件的打开。我也准备好了流式处理的函数和延迟操作。现在我该怎么把它们组合在一起呢?我想把新数据反馈给某个协议的dataReceived()
方法。
当然,我可以创建一个新的对象来设置输入输出监控,并加上合适的回调函数,在反应器关闭时注册一个回调(来关闭文件或协议),然后手动启动一切——但这样做算不算“正确的方法”?有没有什么更好的抽象方式可以使用?我见过reactor.connectWith()
,但它似乎并没有提供太多的抽象...
另外,我该如何把数据从我的读取器传递给协议呢?ITransport
并没有定义任何接口来处理这个,尽管这看起来正是传输的责任所在。
1 个回答
听起来你大致上已经搞清楚怎么做了。你可能会对 twisted.internet.fdesc.readFromFD
感兴趣,但它其实只有几行代码,而且并没有做什么特别复杂的事情(这几行代码你也不需要维护)。除此之外,是的,在这种情况下你需要自己进行输入输出监控,因为普通的文件描述符不支持 select/poll/epoll(它们总是被报告为准备好,这并不是你想要的)。
在 Twisted 中已经对 inotify 的支持做了一些工作(http://twistedmatrix.com/trac/ticket/972),但这还没有完成,所以现在对你来说并没有直接的用处(除非你想帮忙完成它,然后再使用)。假设你只是使用基于时间的轮询,反应器中的大部分内容对你帮助不大,因为那些代码主要是用来利用系统提供的准备好 API(也就是 select/poll/epoll)来触发事件。
不过,对于管道的情况,你应该能够使用并从 IReactorFDSet
的方法中受益,比如 addReader
等等。
你的基于时间的轮询传输可能仍然可以通过实现 ITransport
来受益——虽然我不太确定你该如何为类似 tail -f
的传输实现 write
。你肯定会从让你的传输通过 IProtocol
接口传递数据中受益,因为这简化了代码的重用。IProtocol.dataReceived
正是你想用来从你的 reader(我想这和你的 transport 是一样的,对吧?)传递数据的方式。这在 ITransport
上没有定义,因为这是你在另一个不是传输的对象上调用的方法。
reactor.connectWith
可能对你没有什么帮助。正如你所说的,它并不是一个很好的抽象;我觉得这更像是一个错误。:)
不要太担心不能直接给反应器添加方法。一个接受反应器作为参数的自由函数同样容易使用。
对于关闭回调,addReader
实际上应该能帮你完成大部分工作。在关闭时,反应器中的任何读取器都会调用 connectionLost
(这是 IFileDescriptor
的一部分)。你应该实现这个方法来清理文件和协议。