php做网站的公司有哪些,营销策划思路及方案,廊坊网站建设技术外包,六安房产网From: http://blog.chinaunix.net/uid-20730371-id-765038.html 非阻塞或异步编程例如#xff0c;对于一个聊天室来说#xff0c;因为有多个连接需要同时被处理#xff0c;所以很显然#xff0c;阻塞或同步的方法是不合适的#xff0c;这就像买票只开了一个窗口#xff0…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 serverimport 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三、TwistedTwisted 是针对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的factoryFactory 类在模块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()