python 网络编程----非阻塞或异步编程

From: http://blog.chinaunix.net/uid-20730371-id-765038.html

非阻塞或异步编程

例如,对于一个聊天室来说,因为有多个连接需要同时被处理,所以很显然,阻塞或同步的方法是不合适的,这就像买票只开了一个窗口,佷多人排队等一样。那么我们如何解决这个问题呢?主要有三种方法:forking、threading、异步I/O。

Forking和threading的方法非常简单,通过使用SocketServer服务类的min-in类就可以实现。forking只适用于类Unix平台;threading需要注意内存共享的问题。
异步I/O如果底层的方法来实现是有点困难的。要简单点,我们可以考虑使用标准库中的框架或Twisted(Twisted是一个非常强大的异步网络编程的框架)。

一、用ScoketServer实现Forking和threading

下面我们使用两个例子来分别创建forking服务器和threading服务器。

Forking 服务器

from SocketServer import TCPServer, ForkingMixIn, StreamRequestHandler

class Server(ForkingMixIn, TCPServer): pass

class Handler(StreamRequestHandler):
    def handle(self):
        addr = self.request.getpeername()
        print 'Got connection from', addr
        self.wfile.write('Thank you for connecting')

server = Server(('', 1234), Handler)
server.serve_forever()


threading服务器

from SocketServer import TCPServer, ThreadingMixIn, StreamRequestHandler

class Server(ThreadingMixIn, TCPServer): pass

class Handler(StreamRequestHandler):
    def handle(self):
        addr = self.request.getpeername()
        print 'Got connection from', addr
        self.wfile.write('Thank you for connecting')

server = Server(('', 1234), Handler)
server.serve_forever()


二、使用select实现异步I/O

所谓异步I/O,打个比方,就是如果一大群人都想你听他说话,那么你就给他们每人一分钟的时间说,大家轮流说,没说完的待会儿轮到时再继续说。也就是一个时间片的方法。

要实现异步I/O,我们可以通过使用框架asyncore/asynchat或Twisted,它们都是基于select函数或poll函数(poll只适于类Unix系统)的。select和poll函数都来自select模块。

select 函数要求三个必须序列作为参数和一个可选的以秒为单位的超时值。序列中是表示文件描述符的整数值,它们是我们要等待的连接。这三个序列是关于输入、输出和 异常条件的。如果超时值没有给出的话,select将处于阻塞状态(也就是等待)直到有文件描述符准备动作。如果超时值给出了,那么select只阻塞给 定的时间。如果超时值是0的话,那么将不阻塞。select返回的值是一个由三个序列组成的元组,它们分别代表相应参数的活动的子集。例如,第一个序列返 回的是用于读的输入文件描述符构成的序列。

序列可以包含文件对象(不适于Windows)或socket。下面这个例子创建一个使用 select去服务几个连接的服务器(注意:服务端的socket自身也提供给了select,以便于它能够在有新的连接准备接受时发出信号通知)。这个 服务器只是简单地打印接受自客户端的数据。你可以使用telnet(或写一个基于socket的简单的客户端)来连接测试它。

select server

import socket, select

s = socket.socket()
host = socket.gethostname()
port = 1234
s.bind((host, port))

s.listen(5)
inputs = [s]
while True:
    rs, ws, es = select.select(inputs, [], [])
    for r in rs:
        if r is s:
            c, addr = s.accept()
            print 'Got connection from', addr
            inputs.append(c)
        else:
            try:
                data = r.recv(1024)
                disconnected = not data
            except socket.error:
                disconnected = True

            if disconnected:
                print r.getpeername(), 'disconnected'
                inputs.remove(r)
            else:
                print data





三、Twisted

Twisted 是针对Python的一个事件驱动的网络框架,最初是为了网络游戏而开发的,但是现在被应用于各类网络软件。用Twisted,你可以实现事件处理器,非 常类似用GUI工具包(Tk, GTK, Qt, wxWidgets)。这部分我将介绍一些基本的概念和演示如何使用Twisted来做一些相对简单的 网络编程。Twisted是非常强大的框架并提供了大量的支持,如:Web服务器和客户端、 SSH2, SMTP, POP3, IMAP4, AIM, ICQ, IRC, MSN,Jabber, NNTP, DNS等等。

早先我们所写的基于socket的服务器,它们都有一个显示的事件循环:寻找新的连接和新的数据;基于SocketServer的服务器有一个隐含的循环:寻找连接和为连接创建处理器。但时处理器仍然时显示的读数据。

而 Twisted使用了更多的基于事件的方式。要写一个基本的服务器,你要实现事件处理器,它处理诸如一个新的客户端连接、新的数据到达和客户端连接中断等 情况。在Twisted中,你的事件处理器定义在一个protocol中;你也需要一个factory,当一个新的连接到达时它能够构造这个 protocol对象,但是如果你仅仅想创建一个自定义的Protocol类的实例的话,你可以使用来自Twisted的factory,Factory 类在模块twisted.internet.protocol中。当你写你的protocol时,使用 twisted.internet.protocol模块中的Protocol作为你的父类。当你得到一个连接时,事件处理器 connectionMade被调用;当你丢失了一个连接时,connectionLost被调用。从客户端接受数据使用处理器 dataReceived。但是你不能使用事件处理策略向客户端发送数据;要向客户端发送数据,你可以使用self.transport,它有一个 write方法。它也有一个client属性,其中包含了客户端的地址(主机名和端口)。

下面这个例子是一个Twisted版的服务器。 其中实例化了Factory并设置了它的protocol属性以便它知道使用哪个protocol与客户端通信(这就是所谓的你的自定义 protocol)。然后你使用factory开始监听指定的端口,factory通过实例化的protocol对象处理连接。监听使用reactor模 块中的listenTCP函数。最后,你通过调用reactor模块中的run函数来开始服务器。

from twisted.internet import reactor
from twisted.internet.protocol import Protocol, Factory

# 定义你Protocol类
class SimpleLogger(Protocol):

    def connectionMade(self):
        print 'Got connection from', self.transport.client
    def connectionLost(self, reason):
        print self.transport.client, 'disconnected'
    def dataReceived(self, data):
        print data


# 实例化Factory

factory = Factory()

# 设置factory的protocol属性以便它知道使用哪个protocol与客户端通信(这就是所谓的你的自定义
# protocol)

factory.protocol = SimpleLogger

# 监听指定的端口

reactor.listenTCP(1234, factory)

# 开始运行主程序
reactor.run()


为 你的处理目的而写一个自定义的protocol是很容易的。模块twisted.protocols.basic中包含了几个有用的已存在的 protocol,其中的LineReceiver执行dataReceived并在接受到了一个完整的行时调用事件处理器lineReceived。如 果当你在接受数据时除了使用lineReceived,还要做些别的,那么你可以使用LineReceiver定义的名为rawDataReceived 事件处理器。下面是一使用LineReceiver的服务器例子:

from twisted.internet import reactor
from twisted.internet.protocol import Factory
from twisted.protocols.basic import LineReceiver

class SimpleLogger(LineReceiver):

    def connectionMade(self):
        print 'Got connection from', self.transport.client
    def connectionLost(self, reason):
        print self.transport.client, 'disconnected'
    def lineReceived(self, line):
        print line

factory = Factory()
factory.protocol = SimpleLogger
reactor.listenTCP(1234, factory)
reactor.run()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/404187.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分享一个自定义的 console 类,让你不再纠结JS中的调试代码的兼容

问题的产生 在写JS的过程中,为了调试我们常常会写很多 console.log、console.info、console.group、console.warn、console.error代码来查看JS的运行情况,但发布时又因为IE不支持console,又要去掉这些代码,一不小心就会出错。 本文…

React开发(269):事件的绑定-addEventListener

利用函数addEventListener(‘事件’,function (){})可以是同个元素执行多个程序 复制代码big.addEventListener(click,function(){ console.log("大"); },true) //在函数后面加true可以使这个div在捕捉阶段…

python的UnboundLocalError: local variable 'xxx' referenced before assignment

From: http://blog.sina.com.cn/s/blog_8d3652760101d01p.html 一、意思:本地变量xxx引用前没定义。二、错误原因在于python没有变量的声明 ,所以它通过一个简单的规则找出变量的范围 :如果有一个函数内部的变量赋值 ,该变量被认为是本地的&a…

cmstop框架中的js设计content.js

控制cmstop框架中action的js 内容模块 找出当前页面的js的思路01先找显示页面的当前文件.在页面文件中-->找(编辑,删除)按钮-->找获取这个按钮的js选择器 02看加载的js文件顺序content.js中.定义对象(包含编辑方法)-->html页面中,引入js后,直接调用该方法 content.edi…

React开发(262):react中活动时间回显用moment

<Form.Item label"活动时间">{getFieldDecorator(activityTimeStamp, {initialValue: [moment(activityTimeStamp[0]), moment(activityTimeStamp[1])],rules: [{ required: true, message: 请选择活动时间 }],})(<RangePicker format"YYYY-MM-DD HH:…

用户如何有效地利用数据字典(转)

ORACLE的数据字典是数据库的重要组成部分之一&#xff0c;它随着数据库的产生而产生, 随着数据库的变化而变化,   体现为sys用户下的一些表和视图。数据字典名称是大写的英文字符。   数据字典里存有用户信息、用户的权限信息、所有数据对象信息、表的约束条件、统计分析数…

OS X 平台的 8 个终端实用工具

From: http://blog.jobbole.com/72238/ 本文由 伯乐在线 - shinancao 翻译自 mitchchn。欢迎加入iOS小组。转载请参见文章末尾处的要求。 OS X 终端对外开放了许多很强大的UNIX实用工具和脚本。如果你是从Linux转过来的&#xff0c;你会发现许多熟悉的命令正是按照你想的那样…

内存操作流

可以将输出的位置设置在内存上&#xff0c;此时就要使用ByteArrayInputStream、ByteArrayOutputStream来完成输入和输出功能。 ByteArrayInputStream主要完成将内容写入到内存中 ByteArrayOutputStream的功能主要是将内存中的数据输出 import java.io.ByteArrayInputStream; im…

React开发(263):react中处理时间的判断

if (new Date(values.activityTimeStamp[1]).valueOf() <new Date(values.openTimeStamp[0]).valueOf()) {message.error(活动开始时间需要大于等于申请时间的结束时间);return false;}

OpenSSL(openssl-1.0.1h)编译与安装(Win7)

参考&#xff1a; http://blog.chinaunix.net/uid-20479991-id-216269.html 1. 准备: 1.1 安装perl环境, 下载地址: http://dlsw.baidu.com/sw-search-sp/soft/4a/14792/ActivePerl_5.16.2.3010812913.msi1.2 下载nasm.exe和ndisasm.exe, 地址: http://dldx.csdn.net/fd.php?i…

JDBC连接本地sqlserver2005的方法

主要看这转载&#xff1a;http://wenku.baidu.com/view/7a20f318fad6195f312ba6de.html 或者&#xff1a;http://hi.baidu.com/eyea/blog/item/54ddf20361cf75733912bbf0.html

java分页数据导出excel

/*** 订单导出&#xff08;用于统计利润&#xff09;* return*/public String orderExport() throws IOException{if (queryOrderList_currentPage null || queryOrderList_currentPage < 0) {queryOrderList_currentPage 1;}OrderInfo order new OrderInfo();if (!Strin…

React开发(264):react使用国际化

## 使用国际化locales 国际化词汇文件夹├── en-US 英文├── zh-CN 中文使用方法&#xff1a; jsx import { formatMessage,FormattedMessage } from umi/locale;formatMessage({ id: app.pwa.offline }) <FormattedMessage id"menu.home" defa…

python 十进制与二进制以及位运算

From: http://blog.sina.com.cn/s/blog_681de30a01013uiw.html 在python2.6以上的版本中自带了将十进制转化为二进制的函数bin()。 看一下bin.__doc__怎么说的。 >>>print bin.__doc__ bin(number) -> string return the binary represiontation of an integer or…

分享一套C++入门基础视频

本课程从C起步、用户无需不论什么计算机基础&#xff0c;仅仅须要懂的主要的电脑操作&#xff0c;既可学习本课程。本课程适合在校大学生&#xff0c;在职人员等&#xff0c;通过本课程的学习&#xff0c;学员可掌握C\MFC\VCserver端、网络编程等技能&#xff0c;相比国内几万的…

C/C++的64位整型 zz

From: http://blog.csdn.net/lychee007/article/details/5449237 [cpp] view plaincopy //为了和DSP兼容&#xff0c;TSint64和TUint64设置成TSint40和TUint40一样的数 //结果VC中还是认为是32位的&#xff0c;显然不合适 //typedef signed long int TSint64; //type…

mysql 中 group_concat()用法

基本语法&#xff1a;group_concat([DISTINCT] 要连接的字段 [Order BY 排序字段 ASC/DESC] [Separator 分隔符]) 初始数据&#xff1a; 以name分组&#xff0c;将money打印在一行&#xff0c;默认,分隔&#xff1a; select aa.namename , GROUP_CONCAT( money ) money from a…

C# 设置当前程序调用的dll文件以及其他文件的寻址路径

文件&#xff1a; App.exe为主程序A.dll为需要调用的bll文件B.dll为需要调用的bll文件一般情况下&#xff0c;我们的exe程序会调用一些dll。 由于项目可能较大&#xff0c;有很多的dll文件需要调用&#xff0c;并不可能将这些文件全部放在跟exe同一目录。 但是默认情况下app.ex…

React开发(267):ant design upload简单上传

## 如果只是简单的上传&#xff0c;没必要写 customRequest javascript<Uploadname"file"action{${BASE_URL}/common/file/uploadByStream}headers{{ authorization: localStorage.getItem(token),x-sys-encode: 115992066215908888170874,x-sys-terminal: 159860…

H264(NAL简介与I帧判断)

From: http://blog.csdn.net/jefry_xdz/article/details/8461343 1、NAL全称Network Abstract Layer, 即网络抽象层。 在H.264/AVC视频编码标准中&#xff0c;整个系统框架被分为了两个层面&#xff1a;视频编码层面&#xff08;VCL&#xff09;和网络抽象层面&#…