pythonasyncore异步IO由python标准库学习
# -*- coding: utf-8 -*-
# python:2.x
__author__ = ‘Administrator‘
import asynchat,asyncore,logging,socket
#asyncore异步IO
#作用:异常IO处理
#功能是处理IO对象,如套接字,从而能异步管理这些对象(而不是多个线程或者进程),包括类有dispatcher,这是一个套接字的包装器,提供了一些HOOK(钩子),从主循环函数loo()调用时可以处理连接以及读写事件
#服务器
#第一个类是ECHOServr
#它从客户接收到连接,一旦接受连接,将关闭演示,可以更容易的开始和结束服务器
class ECHOServr(asyncore.dispatcher):
def __init__(self,addres):
self.logger=logging.getLevelName(‘ECHOServr‘)
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET,socket.SOCK_STREAM)
self.bind(addres)
self.address=self.socket.getsockname()
self.logger.debug(‘binding to %s‘%(self.address))
self.listen(1)
def handle_accept(self):
client_INto=self.accept()
self.logger.debug(‘accpet()->%s‘%(client_INto[1]))
EChoHandler(sock=client_INto[0])
self.handle_close()
return
def handle_close(self):
self.logger.debug(‘handle_close()‘)
return
"""
handle_accept()每次接受一个新连接,ECHOServr会创建一个新的EChoHandler实例来管理这个连接,EChoHandler,ECHOServr
在不同的类中定义,因为它们完成不同的工作,ECHOServr接受一全连接一个新的套接字,并非在EChoHandler中将这个套接字分派到单个客户,而是会创建一个EChoHandler
,从而充分利用由asyncore维护套接字映射
"""
class EChoHandler(asyncore.dispatcher):
def __init__(self,sock,chunk_size=256):
self.chunk_size=chunk_size
logger_name=‘EchoHandIer‘
self.logger=logging.getLevelName(logger_name)
asyncore.dispatcher.__init__(self,sock=sock)
self.data_to_write=[]
return
def writable(self):
respone=bool(self.data_to_write)
self.logger.debug(‘%s‘%(respone))
return respone
def handle_write(self):
data=self.data_to_write.pop()
sent=self.send(data[:self.chunk_size])
if sent<len(data):
remaing=data[sent:]
self.data_to_write.append(remaing)
self.logger.debug(‘%d %r‘%(sent,data[:sent]))
if not self.writable():
self.handle_close()
def handle_close(self):
self.logger.debug(‘handle_close()‘)
self.close()
def handle_read(self):
data=self.recv(self.chunk_size)
self.logger.debug(‘%d %r‘%(len(data),data))
self.data_to_write.insert(0,data)
#客户端
#基于asynoce创建一个客户,需要派生dispatcher,并提供实现完成套接字创建和读取,对于EchoClient,可以使用create_socket()在__init__()中创建套接字,也可以提供这个方法其他实现
class EchoClient(asyncore.dispatcher):
def __init__(self,host,port,message,chunk_size=128):
self.message=message
self.to_send=message
self.received_data=[]
self.chunk_size=chunk_size
self.logger=logging.getLevelName(‘EchoClient‘)
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET,socket.SOCK_STREAM)
self.logger.dubug(‘%s‘%(host,port))
self.connect((host,port))
return
def handle_close(self):#hook只是为了它何时得到的调用,其他类型的客户如果需要实际连接握手或者协议协商,则在这个方法呷完成这个工作
self.logger.debug(‘ handle_close()‘)
#下面的handle_close()同样是为了显示它在处理期间何时得到调用,基类中这个方法正确关闭了套接字,如果应该不需要在关闭时做额外的清理工作,这不需要这个方法
def handle_close(self):
self.logger.debug(‘ handle_close()‘)
self.close()
received_message=‘‘.join(self.received_data)
if received_message==self.message:
self.logger.debug(‘RECEIVED COPY OF MESSAGE‘)
else:
self.logger.debug(‘ERROR IN‘)
self.logger.debug(‘%s‘%(self.message))
self.logger.debug(‘%s‘,received_message)
return
def writable(self):#和它的对应方法readable()来确定对每个分派器做何处理,对于各个分派器管理套接字或者文件描述符,poll()或者select()的具体使用在asynoce代码中处理, 不需要在程序使用asynoce实现,这种程序只需要指示分派器希望是读,还是写数据,在这个客户中,只要有数据发到服务器,writeable()返回True,readable()只是True
self.logger.debug(‘%s‘%bool(self.to_send))
return bool(self.to_send)
def readable(self):
self.logger.debug(‘True‘)
return True
#每次通过循环处理时,如果writable()做出肯定的响应,就会调用handle_write(),EchoClients根据给定的大小限制将消息划分多个部分,来展示一个相当大的多部分消息是如何通过循环使用多次迭代进行传输的,每次调用handle_write(),会写下一部分消息,直到消息完全利用完毕
def handle_write(self):
sent=self.send(self.to_send[:self.chunk_size])
self.logger.debug(‘%d %r‘%(sent,self.to_send[:sent]))
self.to_send=self.to_send[sent:]
#类似的readable()做出响应,就调用handle_read()
def handle_read(self):
sent=self.recv(self.chunk_size)
self.logger.debug(‘%d %r‘%(len(sent),sent))
self.received_data.append(sent)
if __name__==‘__main‘:
logging.basicConfig(level=logging.DEBUG,format=‘%(name)-11s(message)s‘,)
address=(‘localhost‘,0)
server=ECHOServr(address)
ip,port=server.address
message=open(‘lorname.txt‘,‘r‘).read()
logging.info((‘%d‘),len(message))
click=EchoClient(ip,port,message=message)
asyncore.loop()
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。