Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Twisted Python中用于从传输读取的模式_Python_Twisted - Fatal编程技术网

Twisted Python中用于从传输读取的模式

Twisted Python中用于从传输读取的模式,python,twisted,Python,Twisted,在TwistedPython中,数据写入协议的传输,但通过覆盖dataReceived方法接收。是否有一种模式用于从传输读取数据?这将有助于使用inlineCallbacks实现状态 例如: class SomeProtocol(Protocol): @defer.inlineCallbacks def login(self): self.transport.write('login') resp = yield self.transport.re

在TwistedPython中,数据写入协议的传输,但通过覆盖dataReceived方法接收。是否有一种模式用于从传输读取数据?这将有助于使用inlineCallbacks实现状态

例如:

class SomeProtocol(Protocol):
    @defer.inlineCallbacks
    def login(self):
        self.transport.write('login')
        resp = yield self.transport.read(5, timeout=1) # this doesn't exist
        if resp != 'user:':
            raise SomeException()
        self.transport.write('admin')
        resp = transport.read(9, timeout=1)
        if resp != 'password:':
            raise SomeException()
        self.transport.write('hunter2')
        # ... etc

在过去的几年中,已经有几次尝试实现类似这样的API。没有人获得任何动力。我想他们现在都被抛弃了

原则上,这并不难实现。您只是将dataReceived回调(推式API)转换为拉式API

实际上,生成的代码是脆弱的,往往包含更多的bug

我认为您试图解决的问题是dataReceived是用于解析字节流的非常低级的原语


有许多可能的解决办法。您可以尝试构建一个更高级别的基于协议的工具,该工具了解协议的各个方面,这基本上就是Twisted中所有协议实现所做的。您还可以查看这样的第三方库,它为处理字节流提供了不同的抽象。

我最终维护了一个延迟回调列表,以在数据到达时对传入数据进行缓冲,直到它满足列表中第一个延迟回调所需的数据长度

class SomeProtocol(Protocol):

    # initialise self.buf and self.readers in __init__

    def deferred_read(self, count, timeout=None):
        """Return a deferred that fires when data becomes available"""
        d = defer.Deferred()
        reader = [d, count]
        timeout_cb = None
        if timeout is not None:
            timeout_cb = self.reactor.callLater(timeout, self.deferred_read_timeout, reader)
        reader.append(timeout_cb)
        self.readers.append(reader)
        self.check_readers()
        return d

    def deferred_read_timeout(self, reader):
        """Timeout this reader and check if others now match"""
        d, count, timeout_cb = reader
        self.readers.remove(reader)
        d.errback(TimeoutException()) # defined elsewhere
        self.check_readers()

    def check_readers(self):
        """Check if there is enough data to satisfy first reader"""
        try:
            while 1:
                reader = self.readers[0]
                d, count, timeout_cb = reader
                if len(self.buf) < count:
                    break
                data = self.buf[:count]
                self.buf = self.buf[count:]
                self.readers.remove(reader)
                try:
                    timeout_cb.cancel()
                except: pass
                d.callback(data)
        except IndexError: pass

    def dataReceived(self, data):
        self.buf += data
        self.check_readers()

它当前要求计数为非零。扩展它以支持返回当前在读取缓冲区中的内容,并在有超时但不计数的情况下读取,以便返回超时后在缓冲区中的内容是很好的。

这已经有几年的历史了,但我只想指出,这就像使用锤子尝试拧下安装的管道一样。如果发送和接收之间确实存在大量时间,那么这可能是合理的,但通常在需要同步读/写时不应该使用异步协议。也就是说,当返回的数据不是自识别的时,同步通信应该优先于异步通信。仅仅因为你使用twisted并不意味着一切都需要基于反应堆…@AlexBaum我很好奇你如何在twisted中实现同步读取而不阻塞反应堆?你有一个例子吗?我根本不会依赖扭曲的架构。就是这样。这并不是说反应堆没有用处,但在过去的几年里,我发现扭曲的反应堆,尽管它做了很多好事,也做了很多坏事。我发现的两个最大的缺点是,它迫使您使用相当多的设置来执行单元测试,这会阻止大多数用户实际编写单元测试。第二种是通过使用calllater和deferred来隐藏堆栈跟踪。如果你想让我提供一个同步的非twisted TCP客户端的例子,我可以。问题是关于如何将其安装到twisted中的模式,因为它是更大系统的一部分-我同意如果你只做这一项任务,那么它更适合同步环境。我真的很喜欢使用trail进行测试,尤其是能够控制时钟对我们的工作来说非常强大。这可能是一个工作的正确工具的问题。