当前位置:编程学习 > 网站相关 >>

Twisted服务器开发技巧(3)

第三种方法是使用经典的服务器模型的select(epoll)异步I/O。使用twisted框架中的reactor(epoll/select)+reader,将磁盘I/O封装为reader,交给reactor来管理,磁盘I/O完成后调用回调函数将数据返回发送改请求的客户端。这样既不会因为I/O阻塞请求处理线程也不会如方法二一样因为I/O阻塞读取线程,详见下图:

 


reactor(epoll/select)+ reader的方法需要继承abstract.FileDescriptor并且实现其几个方法,而twisted框架中的网络(TCP/UDP)、标准I/O、进程都有类似的实现。使用时传入文件描述符,如下:

[python]
fileReader = FileReader(fd, loader_callback, other_data) 
reactor.addReader(fileReader) 
FileReader类的实现如下:

[python] 
class FileReader(abstract.FileDescriptor): 
   
  def __init__(self, fd, result_callback, args): 
    ... 
    self.fd = fd 
self.setNonBlocking(self.fd) 
self.dataRecieved=result_callback 
self.args=args 
self.all_data="" 
  def setNonBlocking(self, fd): 
   ... 
  def fileno(self): 
return self.fd 
  def connectionLost(self, reason): 
sys.close(self.fd) 
  def doRead(self)://fdesc.readFromFD(self.fd, self.dataReceived) 
    data = os.read(self.fd, 10240)     //每次读取1M 
    self.all_data += data 
    if not data: 
       self.dataRecieved(self.all_data , self.args) 
      return CONNECTION_LOST 
自己实现的reader并没有使用类似其他标准实现中的fdesc.readFromFD(self.fd, self.dataReceived)来读取数据,因为该函数中提供的回调函数不允许传参,所以自己将fdesc实现在了FileReader内。

下面是此方法的理论依据:

[python] 
def addReader(self, reader): 
    fd = reader.fileno() 
    if not reads.has_key(fd): 
        selectables[fd] = reader 
        reads[fd] =  1 
        self._updateRegistration(fd) 
def _updateRegistration(self, fd): 
    ... 
    mask = 0 
    if reads.has_key(fd): mask = mask | select.POLLIN 
    poller.register(fd, mask) 
def _doReadOrWrite(self, selectable, fd, event, POLLIN, POLLOUT, log, 
    faildict={ 
        error.ConnectionDone: failure.Failure(error.ConnectionDone()), 
        error.ConnectionLost: failure.Failure(error.ConnectionLost()) 
    }): 
    ... 
    if event & POLLIN: 
      why = selectable.doRead() 
      inRead = True 
       ... 
    if why: 
        self._disconnectSelectable(selectable, why, inRead) 
-----摘自pollreactor.py

[python] 
def _disconnectSelectable(self, selectable, why, isRead, faildict={ 
    error.ConnectionDone: failure.Failure(error.ConnectionDone()), 
    error.ConnectionLost: failure.Failure(error.ConnectionLost()) 
}): 
             ... 
             selectable.connectionLost(f) 

[python]
def _disconnectSelectable(self, selectable, why, isRead, faildict={ 
    error.ConnectionDone: failure.Failure(error.ConnectionDone()), 
    error.ConnectionLost: failure.Failure(error.ConnectionLost()) 
}): 
            ... 
            selectable.connectionLost(f) 
            ... 

补充:Web开发 , Python ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,