我的假设

我假设你已经有一些基本的能力去写python程序,并且直到一些socket编程方面的额知识,如果你没有接触过socket请移步这里 socket module documention, 这个系列中的代码例子都是运行在python2.5 和twisted 8.2.0,程序如果不能正确运行请检查你的python和twisted 的版本.

获取例子代码

你可以在public git repository获取例子代码,如果你可以用git 或者其他的版本管理软件,你可以直接clone 出一份代码:

git clone git://github.com/jdavisp3/twisted-intro.git

缓慢的诗

尽管cpu比网络要快很多,但是网络还是仍旧会比你的脑袋或者眼睛快.所以你要看到cpu-network是怎样运行几乎是不可能的.我们需要的是一个slow server,可以让我们的眼睛看到变化.既然是一个server,那就让我们的server来生产两首颇具诗意的诗吧,在代码仓库的子目录中有John Donne, W.B. Yeats, 和 Edgar Allen Poe 的三首小诗,当然如果换成你自己写的,that will be nice :)
最基本的”poetry server” 的实现在 blocking-server/slowpoetry.py,你可以让他跑起来:

python blocking-server/slowpoetry.py poetry/ecstasy.txt

上面这个命令会开启一个阻塞的服务器,你可以打开这个阻塞服务器的源码看一下,你可以看到我们并没有用到twisted,只有一些简单的socket 操作.它可以在每个固定的延迟后发出固定的数量的字节,默认的它会每0.1s 发出10个字节.你可以通过–num-bytes 和 –delay 来控制时间和字节数,比如下面:

python blocking-server/slowpoetry.py --num-bytes 50 --delay 5 poetry/ecstasy.txt

当这个服务开始运行的时候,它会打印出它监听的端口.默认的,这个是一个随机的端口,你可以通过修改配置让它监听固定的端口,你可以指定它监听的端口如下:

python blocking-server/slowpoetry.py --port 10000 poetry/ecstasy.txt

如果你有netcat 命令的话,你可以测试这个server 通过一下的命令:

netcat localhost 10000

如果一切正常的话,你会看到一条小诗被每次输出一些字节,一旦这首小诗被完全生产出来,服务器会断开连接.

如果你看源码的话你会发现,poetry server 不仅仅是每次输出一些字节,如果你再用其他的client去连接server 的话,其他的client 必须等到第一个client被处理完才会被poetry server 处理. 现在的poetry server 确实很慢啊,慢的我蛋痛.

阻塞的client
在我们的例子中我们的客户端也是阻塞的,它可以从多个server 上一个接一个的读取内容,现在我们给我们的客户端三个任务去执行,就想图片一中的那样.首先我们先启动三个服务器,为三个不同的客户端来服务,如下:

python blocking-server/slowpoetry.py --port 10000 poetry/ecstasy.txt --num-bytes 30
python blocking-server/slowpoetry.py --port 10001 poetry/fascination.txt
python blocking-server/slowpoetry.py --port 10002 poetry/science.txt

接下来我们可以开启阻塞的客户端blocking-client/get-poetry.py来接收小诗了:

python blocking-client/get-poetry.py 10000 10001 10002

客户端会按照顺序的去接收小诗,只有接收完一个才会去接收下一个.你会看到一下的输出:

Task 1: get poetry from: 127.0.0.1:10000
Task 1: got 3003 bytes of poetry from 127.0.0.1:10000 in 0:00:10.126361
Task 2: get poetry from: 127.0.0.1:10001
Task 2: got 623 bytes of poetry from 127.0.0.1:10001 in 0:00:06.321777
Task 3: get poetry from: 127.0.0.1:10002
Task 3: got 653 bytes of poetry from 127.0.0.1:10002 in 0:00:06.617523
Got 3 poems in 0:00:23.065661

基本上就是图片一的文字版本.你可以看一下源代码去定位一下在接收和发送字节的时候那些地方会产生阻塞.

异步的client
下面让我们看看一个简单的异步的client,没有用twisted.先让我们运行一下, async-client/get-poetry.py:

python async-client/get-poetry.py 10000 10001 10002

你将会得到如下的输出:

Task 1: got 30 bytes of poetry from 127.0.0.1:10000
Task 2: got 10 bytes of poetry from 127.0.0.1:10001
Task 3: got 10 bytes of poetry from 127.0.0.1:10002
Task 1: got 30 bytes of poetry from 127.0.0.1:10000
Task 2: got 10 bytes of poetry from 127.0.0.1:10001
...
Task 1: 3003 bytes of poetry
Task 2: 623 bytes of poetry
Task 3: 653 bytes of poetry
Got 3 poems in 0:00:10.133169

这一次的输出结果会比较长因为每当异步的client 每一次从任何一个服务器上获取一些东西都会输出.注意,这个异步的client 会交错的执行三个任务,就像在图片三中描述的那样.

需要注意的是,异步客户端完成任务用了差不多10s,而同步的客户端需要差不多23s,现在回想一下图片三和图片四的区别.通过减少阻塞的时间,我们的异步客户端需要更少的时间.我们的异步的客户端也是会有一些阻塞,但通过交错任务来执行可以减少很多阻塞的时间.

严格的来说,我们的异步client也在执行阻塞操作:它会向stdout输出一些内容.但对我们的例子还没有太大的影响.终端其实一直在准备接收更多的print 的输出,所以print 并不会阻塞,和我们的slow 服务器来说,print语句很快.如果我们的异步程序是一个进程中管道的一部分,在处理标准的输入和输出的时候应该考虑用异步的I/O.twisted 已经提供了在处理标准输入输出时异步I/O 的支持,为了kiss 原则,这里先不用

更进一步的
让我们看一下异步client 的代码,注意异步client代码和同步client代码的区别:

异步的client会一次连接多个server,而同步的client
    异步的client中的socket 通过setblocking(0)设置为了非阻塞的
    select 模块的selsect可以用来监听是否有socket可以提供给client 的数据
    从服务器读数据的时候,异步client会尽可能的多读数据直到这个socket被阻塞,然后如果有其他的socket是可读的话就转到下一个,这意味着我们必须要记录每一首小诗传输状态

这个异步client 中最核心的部分是get_poetry 函数的上层的事件循环,这个循环要经过一下的过程:

用select监听所有打开的sockets,直到其中的一个socket有数据流可以读
    如果有一个socket有数据可读,读取它
    重复循环,直到所有的socket都关闭

同步的client在main 函数中也有一个循环,但是每次遍历的时候同步客户端只下载同一首小诗,直到这首小诗读完.而异步的client在每次循环的时候会读取多个小诗的片段,我们不确定在一次循环中他会读取几个小诗,或者每次读取多少字节, 这完全依赖于服务器的速度以及网络的速度.我们让select 告诉我们哪一个socket有数据可以读,然后我们就可以在不产生阻塞的情况下尽可能多的去读数据了.

假如一个同步的client一直连在一个相同的服务器上(让我们假设是三号服务器),它现在根本不需要一个外部的循环,因为get_poety函数是阻塞的,客户端会一直连在同一个server上,直到获取完整个的一首诗.而异步的客户端没有一个事件循环的话则无法进行下去,异步的客户端需要在一开始的就监听全部的socket,然后在每一次的循环中处理所能收受的所有数据.

这种用一个循环去等待事件的发生,然后去处理事件的模式我们很常见,已经形成了一种设计模式叫做:reactor pattern(反应堆模式),下面这张图比较直观的描述了反应堆模式


the reactor loop

这个循环就是一个反应器因为他在不断的等待事件的发生然后响应他们,因为这个原因也被叫做事件循环.因为”反应器”系统总是等待I/O,这些循环有时也被叫做 select loops,select call 也经常等待I/O. 在一个select loop 中,一个事件就是其中一个socket 变为可读的或者可写的.记住 select 不是等待I/O 的唯一的方法,还有其他的方法被用做等待I/O(比如epoll),他们甚至比select 的性能要好,抛开性能不说,他们都用来做同一件事情:监听一些端口,然后等待其中的一些端口可以读或者可以写.

用select来监测文件描述符来实现一个简单的非阻塞程序是可能的,在" 反应器系统中"执行一些不涉及I/O的操作也是可以的.但是在一个真正的反应器系统中,所有的工作都是I/O相关的

严格的来,咱们的异步client 不是” 反应堆模式”,因为循环的逻辑和也业务逻辑没有完全分开,他们交错在一起.一个真正的反应器模式应该让事件循环作为一个抽象来实现以下两点:

1,接收一些你要处理I/O的文件描述符
    2,当任何一个文件可以读或者可以写的时候,独立的告诉你

一个非常好的反应堆模式还应实现:

可以处理各种操作系统各种奇怪的实现
    提供一个非常好的抽象的实现去帮助你很容易的去应用reactor
    提供各种公开的协议的实现

好吧,其实我们想说的就是twisted,一个具有鲁棒性很强,跨平台的,包罗万象的反应器模式的实现.第三部分我们将开始写一些简单的twisted 代码了.ARE YOU READY?

python twisted教程 二:缓慢的诗相关推荐

  1. python twisted教程_twisted基础教程.pdf

    twisted基础教程 Twisted 网络编程必备(一) 0.1 为什么使用Twisted? 如果你并不准备使用Twisted,你可能有很多异议.为什么使用Twisted 而不是其他网络函数 库或框 ...

  2. python twisted教程 三–开始twisted

    什么也不做,the twisted way 最后我们决定重新用twisted来实现我们异步的读诗的客户端.但首先让我们写一些twisted代码找找twisted 的感觉. 下面是一个简单到屁的twis ...

  3. python twisted教程_Python使用Twisted总结

    最近一直想把Python的Twisted框架好好学习学习,但苦于在生产环境中没有实际的应用,参考网上关于Twisted系列教程,决定深入学习下.Twisted起源于一款游戏,并在游戏中用于商业活动中, ...

  4. python twisted教程_python中twisted实例用法

    python 编程之twisted详解及简单实例 python 编程之twisted详解 前言: 我不擅长写socket代码.一是用c写起来比较麻烦,二是自己平时也没有这方面的需求.等到自己真正想了解 ...

  5. python twisted教程_Python Twisted 学习系列20(转载stulife最棒的Twisted入门教程)

    第二十部分 轮子中的轮子: Twisted和Erlang 简介 在这个系列中,有一个事实我们还没有介绍,即混合同步的"普通Python"代码与异步Twisted代码不是一个简单的任 ...

  6. python twisted教程_Python Twisted系列教程20: Twisted和Erlang

    一个Erlang诗歌代理 让我们看一下Erlang诗歌客户端. 这次我们直接跳入工作版本而不是像在Twisted中慢慢地搭建它.同样,这不是意味着完整版本的Erlang介绍. 但如果这激起了你的兴趣, ...

  7. python twisted教程_Python Twisted系列教程16:Twisted 进程守护

    Fast Poetry 3.0 你可能注意到与其他例子不同, 我们命名了一个不同的目录. 这是因为 twistd 需要插件文件位于 twisted/plugins 目录中, 同时在你的Python搜索 ...

  8. python twisted教程_python-twisted模块代码实例

    Twisted 模块提供了很方便的多任务通信.通过创建协议类来实现. # 客户端 #!/usr/bin/python #coding=utf-8 from twisted.internet impor ...

  9. Python 3 教程二:文件,目录和路径

    1 遍历文件夹和文件 import  os import  os.path #  os,os.path里包含大多数文件访问的函数,所以要先引入它们. #  请按照你的实际情况修改这个路径 rootdi ...

最新文章

  1. 博客文章也能中顶会:ICLR 2022开设博客投稿通道,还有机会跟经典论文原作者直接battle...
  2. 【点击模型学习笔记】Predicting Clicks_Estimating the Click-Through Rate for New Ads_MS_www2007...
  3. 四核处理器_(技术文档)你知道AMD Ryzen处理器中的CCX与CCD是什么吗?
  4. 用C++写的 Levenshtein 算法实现
  5. boost::fusion::any用法的测试程序
  6. C#透明窗体实现方法
  7. Spark配置属性详解
  8. iOS - - JSON 和 XML解析
  9. mysql语句中的注释方法_MySQL语句注释方式简介
  10. oppo鸿蒙系统刷机包下载,oppo A11N原版系统rom固件刷机包下载20200716版卡刷包
  11. Linux 中 $符号是什么意思,代表什么含义
  12. word中使用通配符替换【持续更新系列】
  13. 《走出软件作坊》51:幽幽一缕香
  14. 效果 - 收藏集 - 掘金
  15. java 去掉pdf文字_Java 删除PDF中的附件
  16. 20120817prbs伪随机二进制序列
  17. 紧凑型游戏机械键盘——极度未知HyperX起源60水轴游戏机械键盘
  18. word中自动生成参考文献引用及自动更新文献编号
  19. Python实现飞机大战(搞怪)游戏!这是你没见过的全新版本!
  20. 世界上排名前100的英文歌详细名单及介绍

热门文章

  1. 师弟新作!Nature子刊 | 重大进展!何川团队首次系统地获得了19个组织的5hmC图谱
  2. 中科院动物所团队揭示了空间种子传播集合网络的结构及功能维持机制
  3. 1.6编程基础之一维数组_09向量点积计算
  4. 推荐几款好用的模态框附带教程
  5. 大熊猫学生网页设计模板 静态HTML动物保护学生网页作业成品 DIV CSS大熊猫野生动物主题静态网页
  6. python用动态规划求删除路径_Python | 动态规划求解TSP
  7. Qt笔记-AES加密
  8. HTTP之Content-Security-Policy的使用(C++ Qt框架实现)
  9. C++工作笔记-使用typeid获取对象的类名
  10. Java基础入门笔记-Eclipse快捷操作