【问题标题】:Twisted - Specifying the exact number of bytes coming in dataReceivedTwisted - 指定传入 dataReceived 的确切字节数
【发布时间】:2014-01-17 21:39:59
【问题描述】:

我正在使用 Twisted 创建一个简单的 TCP 服务器。使用 Twisted 协议,是否可以指定 dataReceived 返回的确切字节数?

from twisted.internet.protocol import Factory, Protocol
from twisted.internet.endpoints import TCP4ServerEndpoint
from twisted.internet import reactor

class TestProtocol(Protocol):

    def connectionMade(self):
        print(id(self))
        self.transport.write('hello')

    def connectionLost(self, reason):
        print('connection lost called')

    def dataReceived(self, data):
                    # is it possible to specify size of "data"?
        print('data received called')

class TestFactory(Factory):
    protocol = TestProtocol

endpoint = TCP4ServerEndpoint(reactor, 8007)
endpoint.listen(TestFactory())
reactor.run()

我问这个问题是因为如果我可以控制传入的字节数,我可以避免处理单个 dataReceived 回调中传入的部分协议消息或多个协议消息。

我可以通过在 recv() 方法中指定确切的字节数来使用 asynccore 实现这一点。如果能在 Twisted 中也能做到这一点,那就太好了。

谢谢

...艾伦

【问题讨论】:

    标签: python twisted


    【解决方案1】:

    为什么不定义一个缓冲区并使用它来获取所需大小的消息。 LineReciever 做了类似的事情。

    类似的东西:

    from twisted.internet.protocol import Factory, Protocol
    from twisted.internet.endpoints import TCP4ServerEndpoint
    from twisted.internet import reactor
    
    class TestProtocol(Protocol):
        def __init__(self):
            self.__buffer = ""
            self.frame_size = 3 #FRAME SIZE HERE
    
    
        def connectionMade(self):
            print(id(self))
            self.transport.write('hello')
    
        def connectionLost(self, reason):
            print('connection lost called')
    
        def dataReceived(self, data):
                        # is it possible to specify size of "data"?
            print('data received called')
            self.__buffer = self.__buffer+data
            frame_size = self.frame_size
            while len(self.__buffer) >= frame_size:
                self.frame_received(self.__buffer[0:frame_size])
                self.__buffer=self.__buffer[frame_size:]
    
        def frame_received(self,data):
            print data
    
    
    class TestFactory(Factory):
        protocol = TestProtocol
    
    endpoint = TCP4ServerEndpoint(reactor, 8007)
    endpoint.listen(TestFactory())
    reactor.run()
    

    【讨论】:

    • 您发布的代码不完整,因为它会导致多条消息可能同时进入 dataReceived 的情况下失败。解析流很容易出错,如果有类似 Netty LengthFieldBasedFrameDecoder 的东西就好了。
    • 好点。我认为这种情况可以很容易地使用 while 循环来处理。
    • 修改了代码以处理带有循环的较长消息情况。如果您担心出现错误的可能性,那么您可能想要更多地查看扭曲库(或者也许其他人会在这里发布建议:-)),看看是否有现成的东西可以完成这项工作。祝你好运。
    • 这里是典型的while循环。我以前在 C++ 中做过很多次。然而,这种模式需要两个单元测试用例——流下溢和溢出。大多数人第一次尝试就错了,包括你的帖子。如果我可以指定读取大小,我可以避免这种模式并停止重新发明轮子。
    【解决方案2】:

    只处理部分协议消息。

    Twisted 提供了许多类来帮助您做到这一点in the twisted.protocols.basic package。通常,其中之一应该适合您;必须实现自己的自定义帧协议是很不寻常的。

    如果您正在设计自己的 协议,您可能应该只使用twisted 的内置协议构建工具包Asynchronous Messaging Protocol。 (支持amp-protocol.net 提供的其他语言和框架。

    【讨论】:

    • 基本包似乎不能满足我的需求。我正在实现一个现有协议,它的标头有点像 IPv4 - 非常紧凑且信息丰富。
    • 嗯。 struct 模块是否足以解析其标头?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-26
    相关资源
    最近更新 更多