Python中asyncore异步模块的用法及实现httpclient的实例


Posted in Python onJune 28, 2016

基础
这个模块是socket的异步实现,让我们先来熟悉一下模块中的一些类和方法:
1.asyncore.loop

输入一个轮询循环直到通过计数或打开的通道已关闭。

2.asyncore.dispatcher

dispatcher类是一个底层socket类的包装对象。要使它更有用, 它有一部分事件处理方法被异步循环调用。否则它就是一个标准的非阻塞socket对象。
底层的事件在特定事件或特定的连接状态告诉异步循环,某些高级事件发生了。例如, 我们要求一个socket连接到另一个主机。

(1)handle_connect() 第一次读或写事件。
(2)handle_close() 读事件没有数据可用。
(3)handle_accept 读事件监听一个socket。
(4)handle_read

在异步循环察觉到通道呼叫read()时调用。

(5)handle_write

在异步循环检测到一个可写的socket可以写的时候调用。这种方法经常实现缓冲性能。比如

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

(6)handle_expt

当有(OOB)数据套接字连接。这几乎永远不会发生,因为OOB精细地支持和很少使用。

(7)handle_connect

当socket创建一个连接时调用。

(8)handle_close

当socket连接关闭时调用。

(9)handle_error

当引发一个异常并没有其他处理时调用。

(10)handle_accept

当本地监听通道与远程端建立连接(被动连接)时调用。

(11)readable

每次在异步循环确定是否添加一个通道socket到读事件列表时调用,默认都为True。

(12)writable

每次在异步循环确定是否添加一个通道socket到写事件列表时调用, 默认为True。

(13)create_socket

与创建标准socket的时候相同。

(14)connect

与标准socket的端口设置是相同, 接受一个元组第一个参数为主机地址,第二个参数是端口号。

(15)send

向远程端socket发送数据。

(16)recv

从远程端socket读取最多buffer_size的数据。一个空的字符串意味着从另一端通道已关闭。

(17)listen

监听socket连接。

(18)bind

将socket绑定到地址。

(19)accept

接受一个连接, 必须绑定到一个socket和监听地址。

(20)close

关闭socket。

3.asyncore.dispatcher_with_send

dispatcher子类添加了简单的缓冲输出功能用于简单的客户,更复杂的使用asynchat.async_chat。

4.asyncore.file_dispatcher

file_dispatcher需要一个文件描述符或文件对象地图以及一个可选的参数,包装,使用调查()或循环()函数。如果提供一个文件对象或任何fileno()方法,该方法将调用和传递到file_wrapper构造函数。可用性:UNIX。

5.asyncore.file_wrapper

file_wrapper需要一个整数文件描述符并调用os.dup()复制处理,这样原来的处理可能是独立于file_wrapper关闭。这个类实现足够的方法来模拟一个套接字使用file_dispatcher类。可用性:UNIX。

asyncore 实例

1.一个http client的实现。

import socket
import asyncore

class Client(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 = Client('www.python.org', '/')
asyncore.loop()

服务器接受连接和分配任务

import socket
import asyncore

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_add()
    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()

2.利用asyncore的端口映射(端口转发)

import socket,asyncore

class forwarder(asyncore.dispatcher):
  def __init__(self, ip, port, remoteip,remoteport,backlog=5):
    asyncore.dispatcher.__init__(self)
    self.remoteip=remoteip
    self.remoteport=remoteport
    self.create_socket(socket.AF_INET,socket.SOCK_STREAM)
    self.set_reuse_addr()
    self.bind((ip,port))
    self.listen(backlog)

  def handle_accept(self):
    conn, addr = self.accept()
    # print '--- Connect --- '
    sender(receiver(conn),self.remoteip,self.remoteport)

class receiver(asyncore.dispatcher):
  def __init__(self,conn):
    asyncore.dispatcher.__init__(self,conn)
    self.from_remote_buffer=''
    self.to_remote_buffer=''
    self.sender=None

  def handle_connect(self):
    pass

  def handle_read(self):
    read = self.recv(4096)
    # print '%04i -->'%len(read)
    self.from_remote_buffer += read

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

  def handle_write(self):
    sent = self.send(self.to_remote_buffer)
    # print '%04i <--'%sent
    self.to_remote_buffer = self.to_remote_buffer[sent:]

  def handle_close(self):
    self.close()
    if self.sender:
      self.sender.close()

class sender(asyncore.dispatcher):
  def __init__(self, receiver, remoteaddr,remoteport):
    asyncore.dispatcher.__init__(self)
    self.receiver=receiver
    receiver.sender=self
    self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
    self.connect((remoteaddr, remoteport))

  def handle_connect(self):
    pass

  def handle_read(self):
    read = self.recv(4096)
    # print '<-- %04i'%len(read)
    self.receiver.to_remote_buffer += read

  def writable(self):
    return (len(self.receiver.from_remote_buffer) > 0)

  def handle_write(self):
    sent = self.send(self.receiver.from_remote_buffer)
    # print '--> %04i'%sent
    self.receiver.from_remote_buffer = self.receiver.from_remote_buffer[sent:]

  def handle_close(self):
    self.close()
    self.receiver.close()

if __name__=='__main__':
  import optparse
  parser = optparse.OptionParser()

  parser.add_option(
    '-l','--local-ip',
    dest='local_ip',default='127.0.0.1',
    help='Local IP address to bind to')
  parser.add_option(
    '-p','--local-port',
    type='int',dest='local_port',default=80,
    help='Local port to bind to')
  parser.add_option(
    '-r','--remote-ip',dest='remote_ip',
    help='Local IP address to bind to')
  parser.add_option(
    '-P','--remote-port',
    type='int',dest='remote_port',default=80,
    help='Remote port to bind to')
  options, args = parser.parse_args()

  forwarder(options.local_ip,options.local_port,options.remote_ip,options.remote_port)
  asyncore.loop()
Python 相关文章推荐
Python实现抓取城市的PM2.5浓度和排名
Mar 19 Python
浅谈Python的异常处理
Jun 19 Python
分享一个简单的python读写文件脚本
Nov 25 Python
Python cookbook(数据结构与算法)实现优先级队列的方法示例
Feb 18 Python
Tensorflow 同时载入多个模型的实例讲解
Jul 27 Python
python traceback捕获并打印异常的方法
Aug 31 Python
django创建最简单HTML页面跳转方法
Aug 16 Python
python常用数据重复项处理方法
Nov 22 Python
selenium+python配置chrome浏览器的选项的实现
Mar 18 Python
对Keras中predict()方法和predict_classes()方法的区别说明
Jun 09 Python
Python 分布式缓存之Reids数据类型操作详解
Jun 24 Python
python通过cython加密代码
Dec 11 Python
python 字典(dict)按键和值排序
Jun 28 #Python
简单谈谈python的反射机制
Jun 28 #Python
Python实现带百分比的进度条
Jun 28 #Python
Python中的字符串替换操作示例
Jun 27 #Python
Python的string模块中的Template类字符串模板用法
Jun 27 #Python
Python的Flask框架及Nginx实现静态文件访问限制功能
Jun 27 #Python
总结网络IO模型与select模型的Python实例讲解
Jun 27 #Python
You might like
给apache2.2加上mod_encoding模块後 php5.2.0 处理url出现bug
2007/04/12 PHP
基于php导出到Excel或CSV的详解(附utf8、gbk 编码转换)
2013/06/25 PHP
PHP伪静态Rewrite设置之APACHE篇
2014/07/30 PHP
php获取apk包信息的方法
2014/08/15 PHP
Laravel中间件实现原理详解
2016/10/09 PHP
Yii框架ACF(accessController)简单权限控制操作示例
2019/04/26 PHP
Javascript实现CheckBox的全选与取消全选的代码
2010/07/20 Javascript
js Math 对象的方法
2013/09/01 Javascript
javaScript中with函数用法实例分析
2015/06/08 Javascript
JS实现仿雅虎首页快捷登录入口及导航模块效果
2015/09/19 Javascript
分步解析JavaScript实现tab选项卡自动切换功能
2016/01/25 Javascript
jQuery实现查找最近父节点的方法
2016/06/23 Javascript
Angular.Js的自动化测试详解
2016/12/09 Javascript
bootstrap警告框使用方法解析
2017/01/13 Javascript
详解动画插件wow.js的使用方法
2017/09/13 Javascript
Vue 通过公共字段,拼接两个对象数组的实例
2019/11/07 Javascript
小程序如何定位所在城市及发起周边搜索
2020/02/11 Javascript
[03:55]2014DOTA2国际邀请赛 Fnatic经理采访赢DK在情理之中
2014/07/10 DOTA
浅谈django url请求与数据库连接池的共享问题
2019/08/29 Python
印尼在线旅游门户网站:NusaTrip
2019/11/01 全球购物
Gerry Weber德国官网:优质女性时装,德国最大的时装公司之一
2019/11/02 全球购物
北京SQL新华信咨询
2016/09/30 面试题
数控技术专业推荐信
2013/11/01 职场文书
公司前台接待岗位职责
2013/12/03 职场文书
核心价值观演讲稿
2014/05/13 职场文书
应届毕业生求职信范文
2014/07/07 职场文书
民主生活会剖析材料
2014/09/30 职场文书
三提三创主题教育活动查摆整改措施
2014/10/25 职场文书
继承权公证书范本
2015/01/23 职场文书
幼儿园六一儿童节演讲稿
2015/03/19 职场文书
培训督导岗位职责
2015/04/10 职场文书
2015年副班长工作总结
2015/05/15 职场文书
干货!开幕词的写作方法
2019/04/02 职场文书
Go中的条件语句Switch示例详解
2021/08/23 Golang
python字符串拼接.join()和拆分.split()详解
2021/11/23 Python
世界十大评分最高的动漫,CLANNAD上榜,第八赚足人们眼泪
2022/03/18 日漫