python-asyncore模块


一个异步套接字处理者
源代码: Lib/asyncore.py
这个模块提供了一个基础的基础结构对于写一个异步的套接字客户端和服务器。

这又两种方法去实现一个程序在单一处理器的情况下处理多个事情在一瞬间。多线程编程是最简单的,也是最流行的方法去实现它,但是有一种非常困难的技术,让你可以拥有一切多线程的技术,不需要真的实现多线程。只有当您的程序在很大程度上受I/O限制时,它才真正实用。如果您的程序是处理器绑定的,那么抢占式调度线程可能是您真正需要的。然而,网络服务器很少与处理器绑定。

如果你的操作系统支持select()系统调用在它的i/o库(几乎所有人都这样做了),然后你可以用它来同时切换多个通信通道;做其他的工作当你的I/O发生在后台,虽然这个策略看起来有点奇怪而且复杂,尤其是在一开始的时候,在许多方面,它比多线程编程更容易理解和控制。这个asyn模块为你解决了很多困难问题,使构建复杂的高性能网络服务器和客户机的任务变得非常简单。对于会话程序来说和协议来说,伴随的asynchat是无价的。

这些模块后面的主要思想就是去创建一个或多个网络通道,实例关于class asyncore.dispatcher 和asynchat.async_chat.。创建一个通道,就是把它们添加到一个全局的映射中,被loop函数所使用,如果你不提供你自己的映射。

一旦最初的通道被创建,调用loop()函数激活通道服务,它会一直循环知道最后一个通道(包括任何加入到映射在异步服务的时候)关闭。

asyncore.loop([timeout[, use_poll[, map[, count]]]])
输入一个轮询循环,该循环在count通过或关闭所有打开的通道后终止。所有参数都是可选的。count参数默认为None,导致循环仅在所有通道都关闭时终止。超时参数设置适当的select()或poll()调用的超时参数,以秒为单位度量;默认值是30秒。如果use_poll参数为真,则表示应该使用poll()优先选择select()(缺省值为False)。

map参数是一个字典,其条目是要查看的频道。当通道关闭时,它们将从映射中删除。如果省略map,则使用全局map。通道(asyncore的实例)。调度员,asynchat。async_chat及其子类)可以在映射中自由混合。

类 asyncore.dispatcher
dispatcher类一个简单包装其对于低等级的套接字对象。为了让它更有用,它有几个方法对于事件操作从异步循环中被调用。否则,它可以被视为一个普通的非阻塞套接字对象。

在特定时间或在特定连接状态下触发低级事件告诉异步循环已经发生了特定的高级事件。例如,如果我们请求一个套接字连接到另一个主机,我们知道当套接字第一次成为可写的时候就已经建立了连接(此时,您知道您可能会带着成功的期望向它写入)。隐含的高级事件包括:

事件 描述
handle_connect() 第一个读或写事件所暗示的
handle_close() 没有可用数据的读事件所暗示的
handle_accept() 监听套接字上的读事件所暗示的

在异步处理期间,每个映射通道的可读()和可写()方法用于确定是否应该将通道的套接字添加到用于读写事件的通道select()ed或poll()ed列表中。

因此,通道事件集比基本套接字事件集更大。可以在子类中重写的完整方法集如下:

  • create_socket(family, type)
    这与创建普通套接字相同,并将使用相同的选项进行创建。有关创建套接字的信息,请参阅套接字文档。

  • connect(address)
    与普通套接字对象一样,address是一个元组,其中包含主机要连接的第一个元素,以及第二个端口号。

  • send(data)
    将数据发送到套接字的远程端点。

  • recv(buffer_size)
    从套接字的远程端点读取最多buffer_size字节。空字符串表示通道已从另一端关闭。

注意,recv()可能引发套接字。使用EAGAIN或ewould dblock时出错,即使select.select()或select.poll()报告套接字已准备好读取。

  • listen(backlog)
    监听到套接字的连接。backlog参数指定排队连接的最大数量,并且应该至少为1;最大值依赖于系统(通常为5)。

  • bind(address)
    将套接字绑定到address。套接字必须尚未绑定。(地址的格式取决于地址族—更多信息请参考套接字文档。)要将套接字标记为可重用(设置SO_REUSEADDR选项),请调用dispatcher对象的set_reuse_addr()方法。

  • accept()
    接受一个连接。套接字必须绑定到一个地址并侦听连接。返回值可以是None,也可以是pair (conn, address),其中conn是一个新的套接字对象,用于在连接上发送和接收数据,address是绑定到连接另一端套接字的地址。当返回None时,这意味着连接没有发生,在这种情况下,服务器应该忽略这个事件,继续侦听进一步传入的连接。

  • close()
    关闭套接字。套接字对象上的所有后续操作都将失败。远程端点将不再接收任何数据(在队列数据被刷新之后)。套接字在被垃圾收集时自动关闭。

class asyncore.dispatcher_with_send
一个dispatcher子类,它添加了简单的缓冲输出功能,对于简单的客户机非常有用。要获得更复杂的用法,请使用asynchat.async_chat。

class asyncore.file_dispatcher
file_dispatcher接受一个文件描述符或文件对象,以及一个可选的map参数,并将其包装起来,以便与poll()或loop()函数一起使用。如果提供了file对象或带有fileno()方法的任何东西,就会调用该方法并将其传递给file_wrapper构造函数。可用性:UNIX。

class asyncore.file_wrapper
file_wrapper接受一个整数文件描述符,并调用os.dup()来复制句柄,以便可以独立于file_wrapper关闭原始句柄。这个类实现了足够的方法来模拟一个套接字,供file_dispatcher类使用。可用性:UNIX。

一个异步网络的例子对于基本的HTTP客户端

这是一个非常基础的客户端,使用了dispatcher这个类去实现了它对于套接字的控制

import asyncore, socket

class HTTPClient(asyncore.dispatcher):

    def __init__(self, host, path):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.connect( (host, 80) )
        self.buffer = 'GET %s HTTP/1.0\r\n\r\n' % path

    def handle_connect(self):
        pass

    def handle_close(self):
        self.close()

    def handle_read(self):
        print self.recv(8192)

    def writable(self):
        return (len(self.buffer) > 0)

    def handle_write(self):
        sent = self.send(self.buffer)
        self.buffer = self.buffer[sent:]


client = HTTPClient('www.python.org', '/')
asyncore.loop()

一个异步的基本回应服务器的例子

import asyncore
import socket

class EchoHandler(asyncore.dispatcher_with_send):

    def handle_read(self):
        data = self.recv(8192)
        if data:
            self.send(data)

class EchoServer(asyncore.dispatcher):

    def __init__(self, host, port):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.set_reuse_addr()
        self.bind((host, port))
        self.listen(5)

    def handle_accept(self):
        pair = self.accept()
        if pair is not None:
            sock, addr = pair
            print 'Incoming connection from %s' % repr(addr)
            handler = EchoHandler(sock)

server = EchoServer('localhost', 8080)
asyncore.loop()
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值