Twisted网络框架

1.异步编程模型
2.反应堆模式
3.Twisted框架的基本使用方法
4.使用Twisted框架实现时间戳客户端和服务器

一。目前常用的编程模型有3种:同步编程模型,线程编程模型和异步编程模型

同步编程模型:所有的任务都在一个线程种完成,线程中的任务都是顺序执行的,也就是说,只有当执行完第一个任务,才会执行第二个任务。
线程编程模型:要完成多个任务,可以将这些任务分解,然后启动多个线程,每个线程处理一部分任务,最后再将处理结果合并。这样做的好处是,当一个任务被阻塞后,并不影响其他任务的执行。多线程执行效率的高低在某种程度上取决于计算机是否有多颗CPU,以及每颗CPU有多少个核。
异步编程模型:当一个任务被阻塞后,就会立刻执行另一个任务;在异步编程模型中,从一个任务切换到另一个任务,要么是这个任务被阻塞,要么是这个任务执行完毕。

二。Reactor(反应堆)模式

异步编程模型之所以能监视所有的任务的完成和阻塞情况,是因为通过循环用非阻塞模式执行完了所有的任务。这种用循环体来等待事件发生,然后处理发生事件的模型被设计成了一个模式:Reactor(反应堆)模式.

三。Twisted框架的基本使用方法

1.Twisted的Reactor模式必须通过run函数启动
2.Reactor循环是在开始的进程中,也就是运行在主进程中
3.一旦启动Reactor,就会一直运行下去。Reactor会在程序的控制之下
4.Reactor循环并不会消耗任何CPU资源
5.并不需要显示式创建Reactor循环,只要导入reactor模式就可以了。也就是说,Reactor是Singleton(单件)模式,即在一个程序中只能有一个Reactor
Twisted可以使用不同的Reactor,但需要在导入twisted.internet.reactor之前安装它。
在它之前引用,如:安装pollreactor,把他作为当前的reactor

from twisted.internet import pollreactor
# 安装pollreactor
pollreactor.install()

下面这段代码在reactor循环开始后向终端打印一条消息;hello函数是在reactor启动后被调用的,这就意味着Twisted调用了hello函数。通过调用reactor的callWhenRunning函数,让reactor启动回调callWhenRunning函数指定的回调函数

def hello():
    print('Hello,How are you?')
from twisted.internet import reactor

# 执行回调函数
reactor.callWhenRunning(hello)
print('Starting the reactor.')
reactor.run()

函数回调需要了解以下几点
1.reactor模式是单线程的
2.向Twisted这种交互模型已经实现了reactor循环,这就意味着无须亲自去实现它
3.仍然需要框架来调用自己的代码完成业务逻辑
4.因为在单线程中运行,要想运行自己的代码,必须在reactor循环中调用他们
5.reactor事先并不知道调用代码中的哪个函数

四。使用Twisted框架实现时间戳客户端和服务器

4.1利用Twisted框架实现一个时间戳客户端程序,在Concle中输入字符串,然后按回车键将字符串发送给时间戳服务端,最后时间戳服务端会返回服务器的事件和发送给服务器的字符串

# 导入protocol模块和reactor模块
from twisted.internet import protocol,reactor
host = 'localhost'
port = 9876
# 定义回调类
class MyProtocol(protocol.Protocol):
    # 从Console中采集要发送给服务器的数据,按回车键后,会见数据发送给服务器
    def sendData(self):
        data = input('>')
        if data:
            print('...正在发送 %s' % data)
            # 将数据发送给服务器
            self.transport.write(data.encode(encoding='utf_8'))
        else:
            # 发生异常后,关闭连接
            self.transport.loseConnection()
    # 发送数据
    def connectionMade(self):
        self.sendData()
    def dataReceived(self,data):
        # 输出接收到的数据
        print(data.decode('utf-8'))
        # 调用sendData函数,从Console采集要发送的数据
        self.sendData()
# 工厂类
class MyFactory(protocol.ClientFactory):
    protocol = MyProtocol
    # 下面这句话不知啥意思
    clientConnectionLost = clientConnectionFailed = lambda self,connector,reason:reactor.stop()
# 连接host和port,以及MyFactory类的实例
reactor.connectTCP(host,port,MyFactory())
reactor.run()

4.2利用Twisted框架实现一个时间戳服务端程序,启动后可以等待时间戳客户端程序连接

from twisted.internet import protocol,reactor
from time import ctime
port = 9876
class MyProtocol(protocol.Protocol):
    # 当客户端连接到服务端后,调用该方法
    def connectionMade(self):
        # 获取客户端的IP
        client = self.transport.getPeer().host
        print('客户端',client,'已经连接')
    def dataReceived(self,data): # 他是如何知晓这个data会传进来,又是如何传进来的
        # 接收到客户端发送过来的数据后,向客户端返回服务器的实际
        self.transport.write(ctime().encode(encoding='utf-8') + b' ' + data)
# 创建Factory对象
factory = protocol.Factory()
factory.protocol = MyProtocol
print('正在等待客户端连接')
# 监听端口号,等待客户端的请求
reactor.listenTCP(port,factory)
reactor.run()


上一篇:安装Scrapy时提示需要C++14.0库的解决方案


下一篇:关于Redis客户端显示中文或中文乱码问题的解决