ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python – 正确使用客户端并延迟使用Twisted

2019-05-20 09:42:48  阅读:262  来源: 互联网

标签:python twisted deferred


我用套接字实现了一个基本的SOCKS4客户端,但我的Twisted翻译并不是很好.这是我目前的代码:

import struct
import socket

from twisted.python.failure import Failure

from twisted.internet import reactor
from twisted.internet.defer import Deferred
from twisted.internet.protocol import Protocol, ClientFactory

class Socks4Client(Protocol):
    VERSION = 4
    HOST = "0.0.0.0"
    PORT = 80

    REQUESTS = {
        "CONNECT": 1,
        "BIND": 2
    }

    RESPONSES = {
        90: "request granted",
        91: "request rejected or failed",
        92: "request rejected because SOCKS server cannot connect to identd on the client",
        93: "request rejected because the client program and identd report different user-ids"
    }

    def __init__(self):
        self.buffer = ""

    def connectionMade(self):
        self.connect(self.HOST, self.PORT)

    def dataReceived(self, data):
        self.buffer += data

        if len(self.buffer) == 8:
            self.validateResponse(self.buffer)

    def connect(self, host, port):
        data = struct.pack("!BBH", self.VERSION, self.REQUESTS["CONNECT"], port)
        data += socket.inet_aton(host)
        data += "\x00"

        self.transport.write(data)

    def validateResponse(self, data):
        version, result_code = struct.unpack("!BB", data[1:3])

        if version != 4:
            self.factory.protocolError(Exception("invalid version"))
        elif result_code == 90:
            self.factory.deferred.callback(self.responses[result_code])
        elif result_code in self.RESPONSES:
            self.factory.protocolError(Exception(self.responses[result_code]))
        else:
            self.factory.protocolError(Exception())

        self.transport.abortConnection()

class Socks4Factory(ClientFactory):
    protocol = Socks4Client

    def __init__(self, deferred):
        self.deferred = deferred

    def clientConnectionFailed(self, connector, reason):
        self.deferred.errback(reason)

    def clientConnectionLost(self, connector, reason):
        print "Connection lost:", reason

    def protocolError(self, reason):
        self.deferred.errback(reason)

def result(result):
    print "Success:", result

def error(reason):
    print "Error:", reason

if __name__ == "__main__":
    d = Deferred()
    d.addCallbacks(result, error)

    factory = Socks4Factory(d)
    reactor.connectTCP('127.0.0.1', 1080, factory)

    reactor.run()

>我有一种感觉,我在滥用延迟.这是从我的客户端发送结果的正确方法吗?
>我已经阅读了一些教程,查看了文档,并阅读了与Twisted捆绑在一起的大多数协议,但我仍然无法弄清楚:ClientFactory到底是什么?我是以正确的方式使用它吗?
> clientConnectionLosts被触发了很多.有时我会失去联系并获得成功的回复.怎么会这样?这意味着什么,我应该将其视为错误吗?
>如何确保我的延迟调用只有一个回调/错误回复?

任何提示都表示赞赏.

解决方法:

I have a feeling that I’m abusing Deferred. Is this the right way to send results from my client?

它并不理想,但它也不是完全错误的.通常,您应该尝试将实例化Deferred的代码保持尽可能接近在Deferred上调用Deferred.callback或Deferred.errback的代码.在这种情况下,这些代码段相距很远 – 前者位于__main__中,而后者位于由__main__中的代码创建的类创建的类中.这有点像Demeter法则 – 这两件事之间的步骤越多,软件的耦合越紧密,越不灵活,越脆弱.

考虑为Socks4Client提供一个创建并返回此Deferred实例的方法.然后,尝试使用端点设置连接,以便您可以更轻松地调用此方法:

endpoint = TCP4StreamClientEndpoint(reactor, "127.0.0.1", 1080)
d = endpoint.connect(factory)
def connected(protocol):
    return protocol.waitForWhatever()
d.addCallback(connected)
d.addCallbacks(result, error)

这里需要注意的一点是使用端点,不会调用工厂的clientConnectionFailed和clientConnectionLost方法.端点接管前者(尽管不是后者).

I’ve read a few tutorials, looked at the documentation, and read through most of the protocols bundled with Twisted, but I still can’t figure it out: what exactly is a ClientFactory for? Am I using it the right way?

这就是你正在做的事情. :)它创建用于连接的协议实例.需要工厂,因为您可能会创建与许多服务器(或与一个服务器的多个连接)的连接.但是,很多人在使用ClientFactory时遇到了麻烦,因此最近推出的Twisted API并不依赖于它.例如,您还可以将连接设置为:

endpoint = TCP4StreamClientEndpoint(reactor, "127.0.0.1", 1080)
d = connectProtocol(endpoint, Socks4Client())
...

ClientFactory现在已经不在了.

clientConnectionLosts gets triggered a lot. Sometimes I lose the connection and get a successful response. How is that so? What does this mean, and should I treat it as an error?

每个连接最终都必须丢失.您必须自己决定这是否是错误.如果你已经完成了你想要做的所有事情并且你调用了lostConnection,那么这可能不是一个错误.考虑与HTTP服务器的连接.如果您已发送请求并收到回复,则丢失连接可能不是什么大问题.但如果你只收到一半的回复,那就是问题所在.

How do I make sure that my deferred calls only one callback/errback?

如果您按照上面第一个问题的描述构建代码,那么执行此操作会变得更容易.当在Deferred上使用回调/错误的代码分散在程序的大部分内容时,那么正确地执行此操作变得更加困难.

不过,这只是适当的状态跟踪问题.一旦你推迟了结果,你必须安排知道你不应该给它另一个.一个常见的习惯用法是删除对Deferred的引用.例如,如果要将其保存为协议实例上的属性值,则在给出Deferred其结果时将该属性设置为None.

标签:python,twisted,deferred
来源: https://codeday.me/bug/20190520/1142035.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有