Python----网络编程之Twisted

本文介绍了Python网络编程中的Twisted框架,一个完整的事件驱动网络框架,支持多种协议如TCP、UDP和HTTP。通过一个简单的示例,展示了如何使用Twisted创建服务器和客户端,包括连接管理和数据收发。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Python 大法好 Twisted

众所周知, 网络编程是每一门语言中的重点, 今天我学习了python 网络编程中的Twisted, 怕忘记了这么重要的知识点, 特来记录一下我的学习成果.
特谢参考资料----Python核心编程(美 Wesley Chun著), 我也推荐已经入了门的童鞋们可以阅读这本书, 收获会很大.

在这之前, 我已经学习了Socket, 但是我不想先写Socket的文章, 我也不知道为什么, 就想先写Twisted, 可能Twisted是一个很强大的框架吧! 而且,Twisted其实也挺难的, 我在这介绍的只是简单地复述一次我在这本书里学到的东西, 没有太多关于自己的想法和理解, 而在之后我会继续记录我对Twisted 的深入学习, 废话这么多现在就开始吧!!!

这里先引用一下书本对Twisted的介绍, 觉得无聊的可以跳过这一步

2.6 *Twisted 框架介绍
Twisted 是一个完整的事件驱动的网络框架,利用它既能使用也能开发完整的异步网络应
用程序和协议。在编写本书时,因为它还不是 Python 标准库的一部分,所以必须单独下载并
安装它(可以使用本章末尾的链接)。它提供了大量的支持来建立完整的系统,包括网络协议、
线程、安全性和身份验证、聊天/ IM、DBM 及 RDBMS 数据库集成、Web/因特网、电子邮件、
命令行参数、GUI 集成工具包等。
使用 Twisted 来实现简单的例子,有点小题大做,但是你必须开始使用它,并且该应用
程序就相当于网络应用程序的“hello world”。
与 SocketServer 类似,Twisted 的大部分功能都存在于它的类中。特别是对于该示例,我
们将使用 Twisted 因特网组件中的 reactor 和 protocol 子包中的类。

这一段已经介绍得很明白, 而且你也应该要知道Twisted可以支持很多传输以及应用层协议的, 例如TCP, UDP, HTTP, SSH, FTP等等, 对于这些协议的实现,Twisted都带有客户端和服务端来实现, 同时附带命令行工具, 这对每个配置和部署Twisted框架的应用程序变得非常方便.

接下来这一段是书本做的一个小列子, 是一个很简单的例子, 可是这个例子对于您理解Twisted的工作方式是很有作用的, 我也觉得我是个初学者, 为了理解这个小小的工作方式我也花了很大的功夫.

要使用Twisted 模块, 您需要先 pip, 在命令行输入 pip install twisted , 如果您幸运的话, 您将会成功安装, 不然的话就会像我一样失败.
这难得一开始就卡主我了好吗, 众所周知, 要使用Twisted 模块, 您需要现行下载配置, 方法也很简单, 但是我在WIN上操作他的时候就完全地卡住了我, 您需要先:pip install twisted , 但是在这里, 我的命令行疯狂报错, 我也在网上到处寻找方法, 几个小时过去了,我还是卡在这, 算了, 换到我的 mac OS中去试一试吧, 然后我就在 mac OS中的命令行进行 pip install twisted , 我的天啊, 一下子就装好了好吗, 完全没有报错, 这>…我对 win 系统再失望一次, 如果有大神看到我这里的苦恼, 而且也知道怎么解决在 win 解决这个问题, 请告诉我,谢谢!!
服务端代码:

from twisted.internet import protocol, reactor
from time import ctime

PORT = 21567

class TSServProtocol(protocol.Protocol):
    def connectionMade(self):
        clnt = self.clnt = self.transport.getPeer().host
        print('...connected from:',clnt)
    def dataReceived(self,data):
        self.transport.write(('[%s] %s' % (ctime(),data)).encode())


factory = protocol.Factory()
factory.protocol = TSServProtocol
print('waiting for connection...')
reactor.listenTCP(PORT,factory)
reactor.run()

书中对代码的解释

我们获得 protocol 类并为时间戳服务器调用 TSServProtocol。然后重写了 connectionMade()
和 dataReceived()方法,当一个客户端连接到服务器时就会执行 connectionMade()方法,
而当服务器接收到客户端通过网络发送的一些数据时就会调用 dataReceived()方法。
reactor 会作为该方法的一个参数在数据中传输,这样就能在无须自己提取它的情况下访
问它。
此外,传输实例对象解决了如何与客户端通信的问题。你可以看到我们如何在
connectionMade()中使用它来获取主机信息,这些是关于与我们进行连接的客户端的信息,以
及如何在 dataReceived()中将数据返回给客户端。

客户端代码:

from twisted.internet import protocol, reactor

HOST = 'localhost'
PORT = 21567

class TSClntProtocol(protocol.Protocol):
    def sendData(self):
        data = input('> ')
        if data:
            print('...sending %s...' % data)
            self.transport.write(data.encode())
        else:
            self.transport.loseConnection()


    def connectionMade(self):
        self.sendData()

    def dataReceived(self,data):
        print(data)
        self.sendData()


class TSClntFactory(protocol.ClientFactory):
    protocol = TSClntProtocol
    clientConnectionLost = clientConnectionFailed = \
                           lambda self, connector,reason: reactor.stop()


reactor.connectTCP(HOST, PORT, TSClntFactory())
reactor.run()

书中对代码的解释

类似于服务器,我们通过重写 connectionMade()和 dataReceived()方法来扩展 Protocol,
并且这两者都会以与服务器相同的原因来执行。另外,还添加了自己的方法 sendData(),当
需要发送数据时就会调用它。
因为这次我们是客户端,所以我们是开启与服务器对话的一端。一旦建立了连接,就进
行第一步,即发送一条消息。服务器回复之后,我们就将接收到的消息显示在屏幕上,并向
服务器发送另一个消息。
以上行为会在一个循环中继续,直到当提示输入时我们不输入任何内容来关闭连接。此
时,并非调用传输对象的 write()方法发送另一个消息到服务器,而是执行 loseConnection()来关闭套接字。当发生这种情况时,将调用工厂的 clientConnectionLost()方法以及停止 reactor,
结束脚本执行。此外,如果因为某些其他的原因而导致系统调用了 clientConnectionFailed(),
那么也会停止 reactor。
在脚本的最后部分创建了一个客户端工厂,创建了一个到服务器的连接并运行 reactor。
注意,这里实例化了客户端工厂,而不是将其传递给 reactor,正如我们在服务器上所做的那
样。这是因为我们不是服务器,需要等待客户端与我们通信,并且它的工厂为每一次连接都
创建一个新的协议对象。因为我们是一个客户端,所以创建单个连接到服务器的协议对象,
而服务器的工厂则创建一个来与我们通信。

这里是废话, 喜欢看废话的同学可以看一看

在上述代码中, 书中的列子是使用python2.x版本的, 我把它改成了python3.x 的版本, 具体就是:
第一:print语句那里, 在python3中, print 是一个函数了, 后面的参数带括号, 而书中的没有括号的,
第二:就是在客户端, 在接受用户输入的地方, 书中python2的版本是raw_input(), 而我把根据python3版本改回来了input() , 我差点就忘记了这个版本的变更, 在这花了几分钟思考.
第三:就是关于编码的问题, 我也不做详细解释, 大概就是客户端发送字符的时候要 encode() 非 unicode 的其他 编码, 例如self.transport.write(data.encode())
服务端在把字符添加时间戳后发送的时候也要encode()成非unicode的其他编码,例如self.transport.write(('[%s] %s' % (ctime(),data)).encode())
代码已经托管在 github 上了, 有需要的可以下载运行看看
https://github.com/Rinck/twisted
也可以用 git 命令下载
git@github.com:Rinck/twisted.git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值