【异步编程】    1. 简介                       2. 异步设计问题               3. 使用反射(Reflection) 

【简介】    编写网络程序有很多方法。下面是三种主要方式:        1. 为每个连接建立一个单独的处理进程。        2. 为每个连接建立一个单独的处理线程(脚注1)。 (线程池)
        3. 在一个线程中使用“非阻塞”的系统调用来处理所有的连接。 (回调函数)
    当使用一个线程来处理多个连接时,由应用程序而不是操作系统负责调度。通常通过“为每个已经准备好执行读/写操作的连接调用一个事先已经注册过的函数”这种方法来实现--这种方式常常被称为“异步事件驱动”或是“基于回调机制(callback-based)”的编程。    多线程编程是十分灵活的,但是Python中的“全局解释器锁”机制(Global Interpreter Lock)和高阶的抽象能力限制了其通过多线程编程所获得的潜在性能收益。而Fock操作对Python进程来说也存在许多的不足,例如:Python的后台的引用计数机制不能很好的处理“写时复制”(copy-on-write)和一些共享状态的问题。于是,事件驱动的框架便成为Python网络编程的一个最佳选择。使用事件驱动的框架编程的一个好处是可以用其它的事件驱动的框架来取代程序中的主循环,这直接导致服务器端与客户端代码的同质化,于是编写p2p应用成为可能。    事件驱动的编程也有其灵活的方面。由于每个回调函数都必须尽快返回,因此我们不能在函数级的局部变量中保存持久性信息。此外,像递归等编程技巧也不能使用,因为这会使Python中“递归下降解析”的协议处理器失效。由于需要频繁的编写状态机处理程序(state machines),事件驱动编程向来有难于使用的坏名声。但是Twisted事件驱动编程框架建立在“恰当的使用库,事件驱动的编程要比多线程编程更容易”这样一个假设上。    值得注意的是,如果你真的需要使用多线程编程,那么Twisted仍然给予你使用的自由。这常用来编写一些新代码与旧时的“使用同步机制编写的代码”之间的接口部分。

【异步设计问题】    在Python中,代码通常可以分解为一些可覆写的(override)基类方法调用,这些方法可以由不同的子类实现。在这种情况下,或其它类似的情形下,编程的重点就转换为如何编写不同的子类方法的实现。如果可以预知一个实现中的某个类方法会执行很长时间(例如一些由于cpu或是网络问题导致延迟),则该方法就应该设计为异步执行的方式。这通常意味着要将这个方法转换为基于回调的实现方式。在Twisted中,这也就意味着该方法要返回一个Deferred。    由于每个方法都会迅速返回,因此持久性状态不能保存在局部变量中,而要保存在类的实例变量(instance variables)中。在一些必须使用递归的情况下,要手工维护递归产生的堆栈信息,此时常常使用Python中list类的append和pop方法。由于状态机处理程序非常复杂,将他们分层是一个较好的方式,这样每个状态机都只做一件事--将一个抽象级别的事件转换为下一个更高抽象级别的事件。这使代码十分清晰,并且易于调试。

【使用反射(Reflection)】    使用回调方式编程的一个直接产物就是需要为一些小代码段命名。咋看起来这是一些无关轻重的小事儿,但是如果恰当的处理就会极大的提高编程效率。如果使用严格一致的命名规则,就可以避免大量使用常见的“if-else”或是case语句。例如,在SMTP的客户端代码中,一个类的实例变量会通知服务器它想要做什么,当它接收到SMTP服务器的应答的时候,它只要调用 "do_%s_%s" % (self.state, responseCode) 就可以实现所有的事件驱动操作。这种方法使我们无需再事先注册回调函数,或是在代码中加入大段的“if-else”语句。此外,还可以通过子类来覆写(override)或修改每个应答所对应的操作,而无需编写那些“与应用逻辑不相关”(harness)的代码。SMTP客户端的实现可以在代码twisted/protocols/smtp.py中找到。(函数数组指针)
【脚注】    1. 还存在这个方法的一些变种实现,例如:可以使用一个限制大小的线程池来处理所有的连接。它对该方法做了一些优化,但是本质上仍是相同的。

【Reactor概述】    1. Reactor基础    2. 使用Reactor对象    这个HOWTO文档介绍了Twisted中的reactor类,描述了reactor的基础以及一些相关内容。

【Reactor基础】    reactor是Twisted中事件循环的核心,这个循环用于驱动使用Twisted编写的应用程序。reactor为各种服务(包括网络通讯、线程和事件分派)都提供了基本的接口。    要了解有关reactor和Twsited事件循环的更多信息,请看        HOWTO中关于事件分派的部分:调度和使用Deferred        HOWTO中关于网络通讯的部分:TCP服务器、TCP客户端、UDP网络、使用process        使用thread    reactor有多个变种实现。在默认实现的基础上,每个reactor的变种实现都为支持一些特殊应用进行了相应的优化。关于这些变种实现的更多信息和如何选择一个特定的reactor实现可以参考“选择一个reactor”这一部分。    可以使用“twisted.application.service 中提供的接口”替代“单纯的reactor代码”来配置和运行基于Twisted的application。具体的信息可以参考“使用application”中对application的介绍。

【使用reactor对象】    通过下面的代码引入reactor对象:     -----------------------------------------    |   from twisted.internet import reactor  |     -----------------------------------------    每个reactor的实现都实现了一组常用接口,但是根据所选择的reactor实现的不同,每个reactor实现所支持的接口也会略有不同。下面列出了一些常用的接口:     --------------------------------------------------------------------------         IReactorCore      |     实现了reactor的核心功能        IReactorFDSet     |     使用文件描述符对象        IReactorProcess   |     进程管理(参考“使用Process”)        IReactorSSL       |     提供了SSL网络支持IReactorTCP       |     提供TCP网络支持(参考“编写TCP服务器”和“编写TCP客户端”)
IReactorThreads   |     提供线程的使用与管理支持。(参考“Twisted中的线程”)
        IReactorTime      |     提供调度支持(参考“调度任务”)        IReactorUDP       |     提供UDP网络支持(参考“UDP网络”)        IReactorUNIX      |     提供UNIX socket支持     ---------------------------------------------------------------------------

【编写服务器】    1. 概述    2. 协议       o 使用Protocol       o 一些辅助Protocol       o 状态机    3. 工厂       o 把所有的东西都放里

【概述】    Twisted是一个设计灵活的框架,你可以利用Twisted编写功能强大的服务器。为了保证灵活性,Twisted中使用了分层实现的机制,你用Twisted所编写的服务器也要遵循这种分层的机制。    这份文档描述了Protocol层,在Protocol层中,你可以自己实现对特定协议解析与处理。如果正在实现一个application,那么你应该先看看“为Twisted编写插件”中关于如何开始编写你的Twisted application的介绍,然后在看这份文档。本文只涉及TCP、SSL和UNIX socket服务器,对于UDP相关的问题会用单独的一章来描述。    你的协议处理类通常要继承 twisted.internet.protocol.Protocol。大多数的协议处理类要么继承这个基类,要么继承该基类的某个更适合它使用的子类。依据需要,可以为每个连接都初始化一个协议类的实例,当连接断开的时候就释放这个实例。这意味着“要求持久性保存的配置信息”不能保存在Protocol类中。
    持久性的配置信息通常保存在一个工厂类中,这个类应该从 twisted.internet.protocol.Factory 类继承。默认工厂类的实现只是实例化每一个Protocol类,并为每个Protocol类的实例加一个指向它自己的名为factory的属性。这种方式使每个Protocol类都可以通过这个factory访问或是修改保存在工厂类中的持久性的信息。    能够在多个网络地址或端口上提供相同的服务使十分有用的,这就是为什么工厂类不能监听连接,事实上它对网络环境一无所知。(参考 twisted.internet.interfaces.IReactorTCP.listenTCP 和其它的 IReactor*.listen* API函数)    本文将具体解释上述内容。

【协议】    正如上面所说,protocol和一些辅助的类包含了大部分的代码。一个Twisted协议类会使用一种异步的方法来处理数据。这意味着protocol无需等待某个事件的到来,而是当事件出现在网络上时去响应它。    这儿有一个简单的例子:     ---------------------------------------------------    |   from twisted.internet.protocol import Protocol  |    |   class Echo(Protocol):                           |    |     def dataReceived(self, data):                 |    |       self.transport.write(data)                  |     ---------------------------------------------------    这是一个最简单的协议,它只是简单的写会所有它接受到的数据,它并不响应任何事件。这儿有一个响应其它事件的协议的例子:     --------------------------------------------------------------------------    |   from twisted.internet.protocol import Protocol                         |    |   class QOTD(Protocol):                                                  |    |     def connectionMade(self):                                            |    |       self.transport.write("An apple a day keeps the doctor away\r\n")   |    |       self.transport.loseConnection()                                    |     --------------------------------------------------------------------------    这个协议使用一个谚语来响应初始连接,然后断开连接。    connectionMade这个事件会在建立一个连接对象或是任何问候的时候产生(上面描述的QOTD协议基于RFC 865)。connectionLost事件会在断开一个连接的时候产生。下面的例子描述的这种情况:     --------------------------------------------------------------------------    |   from twisted.internet.protocol import Protocol                         |    |   class Echo(Protocol):                                                  |    |     def connectionMade(self):                                            |    |       self.factory.numProtocols = self.factory.numProtocols + 1          |    |       if self.factory.numProtocols > 100:                                |    |         self.transport.write("Too many user, try again later!\r\n")      |    |         self.transport.loseConnection()                                  |    |     def connectionLost(self, reason):                                    |    |       self.factory.numProtocols = self.factory.numProtocols - 1          |    |     def dataReceived(self, data):                                        |    |       self.transport.write(data)                                         |     --------------------------------------------------------------------------    这里connectionMade和connectionLost相互配合来维护factory中保存的当前激活连接的个数。如果连接数过多,connectionMade事件处理程序就断开连接。

【使用Protocol】    在这个部分中将解释如何方便的测试你的协议。(注意:如果需要编写“产品级”的Twisted服务器,最好去看HOWTO中“为Twisted编写插件”的部分。)    下面的代码将运行上面提过的QOTD服务器。     --------------------------------------------------------------------------    |   from twisted.internet.protocol import Protocol                         |    |   class QOTD(Protocol):                                                  |    |     def connectionMade(self):                                            |    |       self.transport.write("An apple a day keeps the doctor away\r\n")   |    |       self.transport.loseConnection()                                    |    |                                                                          |    |   # 下面的代码令人惊奇                                                      |    |   factory = Factory()                                                    |    |   factory.protocol = QOTD                                                |    |                                                                          |    |   # 服务将在8007端口运行,也可以选择其它大于1024的端口                         |    |   reactor.listenTCP(8007, factory)                                       |    |   reactor.run()                                                          |     --------------------------------------------------------------------------    不要担心最后6行看似神奇代码--本文后面会解释他们的作用。

【辅助Protocol】    许多协议建立在类似的低级抽象上。大多数流行的internet协议是基于行的协议。使用CR-LF的组合标识一行的终结。    然而,也有一些协议是混和型的--他们既有基于行的部分也有基于原始数据的部分,例如HTTP/1.1协议和Freenet协议。    大多数情况下,都可以使用LineReceiver协议。这个协议会分派两个不同的事件处理器--lineReceived和rawDataReceived。默认会对每个行调用lineReceived方法。但是如果调用了setRawMode方法将协议设置为接受原始数据的方式,该协议就会调用rawDataReceived方法来处理到来的数据。直到再次调用setLineMode方法来切换处理函数为止。
 

转载于:https://www.cnblogs.com/zhangjing0502/archive/2012/05/21/2511687.html

高性能服务器编程 Twisted编程基础相关推荐

  1. 《Linux高性能服务器编程》——导读

    前 言 为什么要写这本书 目前国内计算机书籍的一个明显弊病就是内容宽泛而空洞.很多书籍长篇大论,恨不得囊括所有最新的技术,但连一个最基本的技术细节也无法解释清楚.有些书籍给读者展现的是网络上随处可见的 ...

  2. 《Linux高性能服务器编程》学习笔记

    <Linux高性能服务器编程>学习笔记 Linux高性能服务器编程 TCP/IP协议族 TCP/IP协议族体系结构以及主要协议 数据链路层 网络层 传输层 应用层 封装 分用 测试网络 A ...

  3. Linux 高性能服务器编程——多线程编程

    问题聚焦:     在简单地介绍线程的基本知识之后,主要讨论三个方面的内容:     1 创建线程和结束线程:     2 读取和设置线程属性:     3 线程同步方式:POSIX信号量,互斥锁和条 ...

  4. 推荐!适合C++服务器编程初学者的基础开源项目

    入门C++网络编程,刚开始会学习一些基础API或者书上的回射服务器.聊天室.简单HTTP服务器实现,学完上述基础后,我们肯定想大显身手做一个像样项目,但看来看去也不知道该怎么入手,或者不知道一个像样项 ...

  5. linux高性能服务器编程书本总结

    目录 目录分析 第一篇从 1-4章节主要是介绍 计算机网络基础知识和 TCP/IP模型 第二篇 核心篇 5 章到 15 章节 5-6章节 主要介绍 套接字编程API的使用和介绍 7章 是linux 服 ...

  6. Linux高性能服务器编程——书籍阅读笔记

    目录 前言 正文 第一章 1. 零拷贝函数 2. TCP/IP协议族 3. OSPF 4. ARP协议 5. RARP 6. ICMP协议 7. TCP协议 8. UDP协议 9. 封装 第四章 TC ...

  7. Linux 高性能服务器网络编程(一)

    Linux 高性能服务器网络编程 Linux网络编程基础API Socket 地址API 通用socket 地址 专用Sokect地址 IP地址转换函数 创建socket(socket) 命名(绑定) ...

  8. Linux 高性能服务器开发笔记:Reactor 模型定时器 | 网络编程定时器

    本文主要根据游双书本 Linux 高性能服务器开发 学习分析 linux 网络编程常用到的定时器模型,配备详细理解和分析,同时分析了 Linux 内核中定时器的低精度时间轮和高精度定时器实现思路还有 ...

  9. 【Todo】【读书笔记】Linux高性能服务器编程

    在读 /Users/baidu/Documents/Data/Interview/服务器-检索端/<Linux高性能服务器编程.pdf> 其实之前读过,要面试了,需要温习. P260 So ...

最新文章

  1. java qq登陆api_java方式接入QQ登录
  2. python读取输入流_python – 将一个正在运行的程序的输出流传输到其他正在运行的程序的输入流...
  3. MySQL高级 - 查询缓存 - 概述及流程
  4. openai-gpt_您可以使用OpenAI GPT-3语言模型做什么?
  5. 国内规模最大的商业WiFi运营商百米生活挂牌新三板
  6. 直播预告丨统一便捷的数据操作平台CloudQuery年终发布!
  7. 一瓶可乐的自动售货机指令“旅程”
  8. C语言程序项目计划书,(C语言程序设计课程设计计划书.doc
  9. python入门基础语法总结
  10. petshop架构分析
  11. TensorFlow中的compile和fit操作,简化神经网络模型代码
  12. r语言与数据挖掘最佳实践和经典案例数据_R语言与数据挖掘最佳实践和经典案例...
  13. 准备给ubuntu18.04安装杀毒软件
  14. vs2019,C#,MySQL创建图书管理系统3(管理员相关页面的布局和设计实现,图书显示,图书添加)
  15. 基于JAVA+SpringBoot+Mybatis+MYSQL的相册管理系统
  16. 诺顿误杀系统文件 导致百万台电脑处于崩溃边缘
  17. 原生js:淘宝轮播图
  18. xampp control-panel深深的坑
  19. auto.js 公众号自动签到
  20. 八皇后问题动态演示_Qt5实现

热门文章

  1. https的ssl证书申请及服务器的nginx的配置教程
  2. Spring MVC拦截器实现用户登录权限验证案例
  3. 04-07 接口请求构造
  4. base | 数值运算符和逻辑运算符
  5. 15 张前端高清知识地图,强烈建议收藏
  6. “360行,行行转前端”:前端岗为什么这么火?
  7. 前端、后端、全栈都要学什么?薪资前景如何?
  8. LeetCode 第 69 场力扣双周赛
  9. 华为mate10手机听筒测试软件,华为mate 10功能说:这几个设置,让你通话体验直线上升,简直了!...
  10. 调用模块里的action_初级测试人员进阶必备Python编码模块,看过的都说好