asyncore模块

+-------------+           +--------+
| driver code |---------> | loop() |
+-------------+           +--------+
      |                      |
      |                      | loop-dispatcher API (a)
      |                      |
      |                  +--------------+
      |                  | dispatcher   |
      +----------------->| subclass     |
                         +--------------+
                             |
                             | dispatcher-logic API (b)
                             |
                         +--------------+
                         | server logic |
                         +--------------+
  • 该模块文件包含一个loop()函数和一个dispatcher基类,其中loop()函数是全局函数,负责检查一个保存着dispatcher实例的dict,也被称为channel。
  • 每一个继承dispatcher类的对象,都可以看作需要处理的socket,因此使用时我们只需定义一个继承dispatcher的类,然后重写一些方法就行,一般都是以handle_开头的方法。

先看一下官方的实例:

import asyncore, socket
class http_client(asyncore.dispatcher):
#must subclass the asyncore.dispatcher
  def __init__(self, host, path):
    asyncore.dispatcher.__init__(self)
    #reload the __init__(self) of asyncore.dispatcher
    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:]
c = http_client('www.python.org', '/')
asyncore.loop()
  • writable和readable在检测到一个socket可以写入或者数据到达的时候,被调用,并返回一个bool来决定是否handle_read或者handle_write。
  • 上面实例可以看出,read状态始终是开启的,从socket读取数据;而write状态是当缓冲区还有数据未发送完,那就调用handle_write将缓冲区数据写入到socket发送出去,即调用socket的send方法。
  • 当一个http服务器发送处理完成你的请求,关闭socket的时候,我们的handle_close()也相应完成自己的使命。close()将对象自身从channel中删除,并且负责销毁socket对象。
    def close(self):
    self.del_channel()
    self.socket.close()
  • loop()函数检测到一个空的channel时退出循环,程序完成任务,exit。

set_reuse_addr()

try to re-use a server port if possible。TCP特性:Port Number会被保留一段时间即使Ctrl + C中断通讯,除非使用set_reuse_addr()才有辦法复用Port Number。

def set_reuse_addr(self):
        # try to re-use a server port if possible
        try:
            self.socket.setsockopt(
                socket.SOL_SOCKET, socket.SO_REUSEADDR,
                self.socket.getsockopt(socket.SOL_SOCKET,
                                       socket.SO_REUSEADDR) | 1
                )
        except socket.error:
            pass

参考文章:
http://blog.chinaunix.net/uid-27571599-id-3492538.html
http://www.jb51.net/article/55804.htm
http://parijatmishra.blogspot.com/2008/01/writing-server-with-pythons-asyncore.html
http://liuj.fcu.edu.tw/net_pg/2012_ln/4-19_2.html

最后由 oucb 编辑于2016年05月04日 13:00