{"id":2833,"date":"2025-03-16T12:20:13","date_gmt":"2025-03-16T04:20:13","guid":{"rendered":"https:\/\/www.laixuexila.com\/?p=2833"},"modified":"2025-03-16T12:20:13","modified_gmt":"2025-03-16T04:20:13","slug":"python3-%e7%bd%91%e7%bb%9c%e7%bc%96%e7%a8%8b8%ef%bc%9atwisted%ef%bc%9a%e9%ab%98%e7%ba%a7%e7%bd%91%e7%bb%9c%e7%bc%96%e7%a8%8b%e6%a1%86%e6%9e%b6","status":"publish","type":"post","link":"https:\/\/www.laixuexila.com\/index.php\/2025\/03\/16\/python3-%e7%bd%91%e7%bb%9c%e7%bc%96%e7%a8%8b8%ef%bc%9atwisted%ef%bc%9a%e9%ab%98%e7%ba%a7%e7%bd%91%e7%bb%9c%e7%bc%96%e7%a8%8b%e6%a1%86%e6%9e%b6\/","title":{"rendered":"Python3 \u7f51\u7edc\u7f16\u7a0b8\uff1aTwisted\uff1a\u9ad8\u7ea7\u7f51\u7edc\u7f16\u7a0b\u6846\u67b6"},"content":{"rendered":"\n<p><code>Twisted<\/code> \u662f\u4e00\u4e2a\u975e\u5e38\u5f3a\u5927\u7684\u5f02\u6b65\u7f51\u7edc\u7f16\u7a0b\u6846\u67b6\uff0c\u652f\u6301\u591a\u79cd\u534f\u8bae\uff08\u5982 HTTP\u3001FTP\u3001SMTP\u3001Telnet\u3001DNS \u7b49\uff09\u3002\u5b83\u63d0\u4f9b\u4e86\u9ad8\u5ea6\u7075\u6d3b\u7684 API\uff0c\u975e\u5e38\u9002\u7528\u4e8e\u6784\u5efa\u590d\u6742\u7684\u7f51\u7edc\u5e94\u7528\u3002<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>8.1 <code>Twisted<\/code> \u57fa\u7840<\/strong><\/h2>\n\n\n\n<p><code>Twisted<\/code> \u4f7f\u7528\u4e8b\u4ef6\u9a71\u52a8\u7684\u7f16\u7a0b\u6a21\u578b\uff0c\u53ef\u4ee5\u5904\u7406\u5927\u91cf\u7684\u5e76\u53d1\u8fde\u63a5\uff0c\u800c\u65e0\u9700\u521b\u5efa\u591a\u7ebf\u7a0b\u6216\u591a\u8fdb\u7a0b\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>8.1.1 \u5b89\u88c5 <code>Twisted<\/code><\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>pip install twisted<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>8.1.2 \u7b80\u5355\u7684 TCP \u670d\u52a1\u5668\u548c\u5ba2\u6237\u7aef<\/strong><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>8.1.2.1 TCP \u670d\u52a1\u5668<\/strong><\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>from twisted.internet import protocol, reactor\n\nclass EchoServer(protocol.Protocol):\n    def dataReceived(self, data):\n        print(f\"\u6536\u5230\u6570\u636e: {data.decode()}\")\n        self.transport.write(b\"Hello from Twisted Server\")\n\nclass EchoServerFactory(protocol.Factory):\n    def buildProtocol(self, addr):\n        return EchoServer()\n\nreactor.listenTCP(1234, EchoServerFactory())\nprint(\"Twisted \u670d\u52a1\u5668\u8fd0\u884c\u5728\u7aef\u53e3 1234...\")\nreactor.run()<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>8.1.2.2 TCP \u5ba2\u6237\u7aef<\/strong><\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>from twisted.internet import defer, protocol, reactor\n\nclass EchoClient(protocol.Protocol):\n    def connectionMade(self):\n        self.transport.write(b\"Hello Twisted Server\")\n\n    def dataReceived(self, data):\n        print(f\"\u6536\u5230\u670d\u52a1\u5668\u54cd\u5e94: {data.decode()}\")\n        self.transport.loseConnection()\n\nclass EchoClientFactory(protocol.ClientFactory):\n    def buildProtocol(self, addr):\n        return EchoClient()\n\n    def clientConnectionFailed(self, connector, reason):\n        print(\"\u8fde\u63a5\u5931\u8d25\")\n        reactor.stop()\n\nreactor.connectTCP(\"127.0.0.1\", 1234, EchoClientFactory())\nreactor.run()<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>8.2 <code>Twisted<\/code> \u4e0e WebSocket<\/strong><\/h2>\n\n\n\n<p><code>Twisted<\/code> \u8fd8\u652f\u6301 WebSocket \u534f\u8bae\uff0c\u53ef\u4ee5\u7528\u4e8e\u6784\u5efa\u590d\u6742\u7684 WebSocket \u670d\u52a1\u5668\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>8.2.1 WebSocket \u670d\u52a1\u5668<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>from twisted.internet import reactor\nfrom twisted.protocols import basic\nfrom twisted.web import server\nfrom twisted.web.resource import Resource\nfrom twisted.protocols.web import WebSocketHandler\n\nclass WebSocketEchoHandler(WebSocketHandler):\n    def connectionMade(self):\n        print(\"WebSocket \u8fde\u63a5\u5df2\u5efa\u7acb\")\n\n    def dataReceived(self, data):\n        print(f\"\u6536\u5230\u6570\u636e: {data}\")\n        self.sendMessage(f\"\u670d\u52a1\u5668\u56de\u4f20: {data}\")\n\n    def connectionLost(self, reason):\n        print(\"WebSocket \u8fde\u63a5\u5df2\u65ad\u5f00\")\n\nclass WebSocketResource(Resource):\n    def render(self, request):\n        return \"WebSocket \u670d\u52a1\"\n\nsite = server.Site(WebSocketResource())\nreactor.listenTCP(8765, site)\nprint(\"Twisted WebSocket \u670d\u52a1\u5668\u8fd0\u884c\u5728\u7aef\u53e3 8765...\")\nreactor.run()<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>8.2.2 WebSocket \u5ba2\u6237\u7aef<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>import asyncio\nfrom autobahn.asyncio.websocket import WebSocketClientProtocol, WebSocketClientFactory\nfrom autobahn.asyncio.websocket import connect\n\nclass MyClientProtocol(WebSocketClientProtocol):\n    def onOpen(self):\n        self.sendMessage(b\"Hello WebSocket Server!\")\n\n    def onMessage(self, payload, isBinary):\n        print(f\"\u6536\u5230\u6d88\u606f: {payload.decode()}\")\n        self.sendClose()\n\n    def onClose(self, wasClean, code, reason):\n        print(\"WebSocket \u8fde\u63a5\u5df2\u5173\u95ed\")\n\nclass MyClientFactory(WebSocketClientFactory):\n    protocol = MyClientProtocol\n\nuri = \"ws:\/\/127.0.0.1:8765\"\nfactory = MyClientFactory(uri)\n\nloop = asyncio.get_event_loop()\nloop.run_until_complete(connect(factory))<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong>\u63d0\u793a<\/strong>\uff1a<code>Twisted<\/code> \u662f\u4e00\u4e2a\u975e\u5e38\u5f3a\u5927\u7684\u6846\u67b6\uff0c\u9002\u7528\u4e8e\u6784\u5efa <strong>\u9ad8\u6027\u80fd\u3001\u9ad8\u5e76\u53d1<\/strong> \u7684\u7f51\u7edc\u670d\u52a1\uff0c\u7279\u522b\u662f\u5f53\u9700\u8981\u652f\u6301\u591a\u4e2a\u534f\u8bae\u65f6\u3002<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>8.3 <code>Twisted<\/code> \u4e0e HTTP \u670d\u52a1<\/strong><\/h2>\n\n\n\n<p><code>Twisted<\/code> \u4e5f\u975e\u5e38\u9002\u5408\u6784\u5efa HTTP \u670d\u52a1\u5668\uff0c\u53ef\u4ee5\u5904\u7406\u590d\u6742\u7684 HTTP \u8bf7\u6c42\u548c\u54cd\u5e94\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>8.3.1 HTTP \u670d\u52a1\u5668<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>from twisted.web import server, resource\nfrom twisted.internet import reactor\n\nclass SimpleResource(resource.Resource):\n    isLeaf = True\n\n    def render_GET(self, request):\n        return b\"Hello from Twisted HTTP Server!\"\n\nsite = server.Site(SimpleResource())\nreactor.listenTCP(8080, site)\nprint(\"Twisted HTTP \u670d\u52a1\u5668\u8fd0\u884c\u5728\u7aef\u53e3 8080...\")\nreactor.run()<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>8.4 \u5f02\u6b65\u4efb\u52a1\u4e0e <code>Deferred<\/code><\/strong><\/h2>\n\n\n\n<p><code>Twisted<\/code> \u4e2d\u7684 <code>Deferred<\/code> \u5bf9\u8c61\u7528\u4e8e\u8868\u793a\u4e00\u4e2a\u5c1a\u672a\u5b8c\u6210\u7684\u64cd\u4f5c\uff0c\u5b83\u662f\u4e8b\u4ef6\u9a71\u52a8\u7f16\u7a0b\u7684\u6838\u5fc3\u3002\u53ef\u4ee5\u901a\u8fc7 <code>addCallback<\/code> \u548c <code>addErrback<\/code> \u65b9\u6cd5\u5904\u7406\u7ed3\u679c\u6216\u9519\u8bef\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>8.4.1 \u4f7f\u7528 <code>Deferred<\/code><\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>from twisted.internet import defer, reactor\n\ndef success(result):\n    print(f\"\u64cd\u4f5c\u6210\u529f: {result}\")\n\ndef failure(failure):\n    print(f\"\u64cd\u4f5c\u5931\u8d25: {failure}\")\n\ndef async_task():\n    d = defer.Deferred()\n    reactor.callLater(2, d.callback, \"\u4efb\u52a1\u5b8c\u6210\")  # \u6a21\u62df\u4efb\u52a1\u5b8c\u6210\n    return d\n\nd = async_task()\nd.addCallback(success)\nd.addErrback(failure)\n\nreactor.run()<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><strong>\u4e0b\u7bc7\u6587\u7ae0\u6211\u4eec\u5c06\u4ecb\u7ecd\u5982\u4f55\u4f7f\u7528 <code>asyncio<\/code> \u548c <code>Twisted<\/code> \u6765\u521b\u5efa\u9ad8\u6548\u7684\u5f02\u6b65 HTTP API\uff01<\/strong> <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Twisted \u662f\u4e00\u4e2a\u975e\u5e38\u5f3a\u5927\u7684\u5f02\u6b65\u7f51\u7edc\u7f16\u7a0b\u6846\u67b6\uff0c\u652f\u6301\u591a\u79cd\u534f\u8bae\uff08\u5982 HTTP\u3001FTP\u3001SMTP\u3001Telnet\u3001 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":2834,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[79],"tags":[],"class_list":["post-2833","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-python-3-"],"_links":{"self":[{"href":"https:\/\/www.laixuexila.com\/index.php\/wp-json\/wp\/v2\/posts\/2833","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.laixuexila.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.laixuexila.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.laixuexila.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.laixuexila.com\/index.php\/wp-json\/wp\/v2\/comments?post=2833"}],"version-history":[{"count":1,"href":"https:\/\/www.laixuexila.com\/index.php\/wp-json\/wp\/v2\/posts\/2833\/revisions"}],"predecessor-version":[{"id":2835,"href":"https:\/\/www.laixuexila.com\/index.php\/wp-json\/wp\/v2\/posts\/2833\/revisions\/2835"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.laixuexila.com\/index.php\/wp-json\/wp\/v2\/media\/2834"}],"wp:attachment":[{"href":"https:\/\/www.laixuexila.com\/index.php\/wp-json\/wp\/v2\/media?parent=2833"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.laixuexila.com\/index.php\/wp-json\/wp\/v2\/categories?post=2833"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.laixuexila.com\/index.php\/wp-json\/wp\/v2\/tags?post=2833"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}