欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

network.py

Python实现的半同步半异步网络框架.在其上可以实现自己的应用层协议,以支持特定的应用.
PY
字号:
#!/usr/bin/python
import asyncore,socket
import time,sys
import threading,Queue
#from  NWPacket import *
#waitingQue=Queue.Queue()
class ClientSys:
  #will rewrite
  currentID=0
  def gen_guid(self):
    #just for test,will rewrite later
    self.currentID=self.currentID+1
    return self.currentID
    

class NWPacket:
  #wil rewrite???
  GOON_STATUS=0
  FULL_STATUS=1
  OVER_STATUS=2
  HEADER_LEN=12
  def __init__(self):
    self.buf=[]
    self.status=self.GOON_STATUS

  def append_data(self,data):
    if self.status==self.FULL_STATUS:
      self.status=self.OVER_STATUS
    if self.status==self.GOON_STATUS:
      idx=data.find('^')
      
      if idx!=-1 and idx==len(data)-1:
        self.status=self.FULL_STATUS
      if idx!=-1 and idx<len(data)-1:
        self.status=self.OVER_STATUS
    self.buf.append(data)
  def trunc(self):
    if self.status==self.GOON_STATUS or self.status==self.FULL_STATUS:
      return ''
    str=''.join(self.buf)
    idx1=str.find('CDAL')

    idx2=str.find('^',idx1)
    strPacket=str[idx1:idx2+1]
    strTrunc=str[idx2+1:]
    self.buf=[strPacket,]
    self.status=self.FULL_STATUS
    return strTrunc
  def string(self):
    return ''.join(self.buf)
  def body(self):
    if self.status!=self.FULL_STATUS:
      return ''
    str=''.join(self.buf)
    idx1=str.find('CDAL')

    idx2=str.find('^',idx1)
    return str[idx1+4:idx2]
    

class NWEvent:
  #a event=clientID++type+packet
  NW_READ_TYPE=0
  NW_WRITE_TYPE=1
  NW_ACTIVE_CLOSE_TYPE=2
  NW_PASSIVE_CLOSE_TYPE=3
  NW_CLIENT_CONNECT_TYPE=4
  def __init__(self,clientID,type,p=None):
    self.clientID=clientID
    self.type=type
    self.packet=p
    
class NWEventQue:  
  def __init__(self):
    self.recvQue=Queue.Queue()
    self.sendQues={}
  def create_send_que(self,clientID):
    #need erro check??
    self.sendQues[clientID]=Queue.Queue()
  def del_send_que(self,clientID):
    try:del self.sendQues[clientID]
    except:
      print clientID,' is not existent'
  def  nw_put(self,e):
    self.recvQue.put(e)
  def nw_get(self,clientID):
    #for there are many clients,the NWEventQue also do the demultiplex for Network Layer while putting a event into sendQues
    
    return self.sendQues[clientID].get()
  def app_put(self,e):
    try:
      sendQue=self.sendQues[e.clientID]
      sendQue.put(e)
      return True
    except:
      return False
      

  def app_get(self):
    return self.recvQue.get()
    
class Network:
  #the network sys interface for the upper application 
  def __init__(self):
    self.que=NWEventQue()
    self.server=Server(self.que)
    
  def start_server(self,port):
    #run in a separate thread
    self.t=threading.Thread(target=self.__start_network,args=(port,))
    self.t.start()
  def __start_network(self,*args):
    port=args[0]
    print port
    self.server.start(port)
    asyncore.loop()
  def get_a_event(self):
    que=self.que
    e=que.app_get()
    return e
  def put_a_event(self,e):
    que=self.que
    que.app_put(e)

    
class Server(asyncore.dispatcher):
  def __init__(self,que):
    self.que=que
    self.clientSys=ClientSys()
    asyncore.dispatcher.__init__(self)
    
  def start(self,port):
    print 'Server is starting...'
    self.create_socket(socket.AF_INET,socket.SOCK_STREAM)
    self.bind(('',port))
    self.listen(5)
    print 'OK!Ready to accept'
  
  def writable(self):
    return 0
  def handle_accept(self):
    que=self.que
    c,addr=self.accept()    
    print 'Client: ',addr,' connected'
    id=self.clientSys.gen_guid()
    c=ClientHandler(id,c,self.que)
    #a client connnected
    #que.nw_put(NWEvent(c.clientID,NWEvent.NW_CLIENT_CONNECT_TYPE,))
    
    
class ClientHandler(asyncore.dispatcher):
  def __init__(self,id,sock,que):
    print 'Create a handler for ',id
    self.clientID=id
    self.que=que
    self.idxSBuf=0
    self.sBuf=''
    self.rPacket=NWPacket()
    self.que.create_send_que(self.clientID)
    asyncore.dispatcher.__init__(self,sock)
  
  def handle_read(self):
    print 'Client',self.clientID,'handle_read()'
    que=self.que
    clientID=self.clientID
    que=self.que
    
    data=self.recv(1024)
    
    self.rPacket.append_data(data)
    print 'Current packet is ',self.rPacket.string()
    while True:
      #process the packet
      packet=self.rPacket
      if packet.status==packet.GOON_STATUS:
        break
      elif packet.status==packet.FULL_STATUS:
        print 'Read a full packet,put into queue'
        print 'Current packet body is ',packet.body()
        que.nw_put(NWEvent(clientID,NWEvent.NW_READ_TYPE,packet))
        self.rPacket=NWPacket()
        break
      elif packet.status==packet.OVER_STATUS:
        print 'Packet overflow ,trunc it'           
        overData=packet.trunc()
        print 'Current packet body is ',packet.body()
        que.nw_put(NWEvent(clientID,NWEvent.NW_READ_TYPE,packet))
        self.rPacket=NWPacket()
        self.rPacket.append_data(overData)
    

  def readable(self):
    full=self.que.sendQues[self.clientID].full()
    return not full
  
  def writable(self):
    que=self.que
    clientID=self.clientID
    empty =que.sendQues[clientID].empty()
    return len(self.sBuf)!=0 or not empty
  
  def handle_write(self):
    print 'Client',self.clientID,' handle_write()'
    que=self.que
    clientID=self.clientID
    if self.sBuf=='':
      #get a packet from buffer queue
      print 'Try to get a event from event queue'
      e=que.nw_get(clientID)
      if e.type==e.NW_ACTIVE_CLOSE_TYPE:
        self.close()
     
      elif e.type==e.NW_WRITE_TYPE:
        
        packet=e.packet
        self.sBuf=packet.string()
        self.idxSBuf=0
        lenSBuf=len(self.sBuf)
    i=self.send(self.sBuf[self.idxSBuf:])
    self.idxSBuf+=i
    #All data in one packet is sended
    if self.idxSBuf==lenSBuf:
      self.sBuf=''
  def close(self):
    #some clean work is done here
    que=self.que
    clientID=self.clientID
    que.del_send_que(clientID)
    asyncore.dispatcher.close(self)
  def handle_close(self):
    print 'Client ',self.clientID,'handle_close()'
    clientID=self.clientID
    que=self.que
    
    self.close()
    self.que.nw_put(NWEvent(clientID,NWEvent.NW_PASSIVE_CLOSE_TYPE))


def test():
  nw=Network()
  nw.start_server(9999)
  print 'App enter event loop...'
  while True:
    
    e=nw.get_a_event()
    e1=NWEvent(e.clientID,e.NW_WRITE_TYPE,e.packet)
    nw.put_a_event(e1)
    
    print'Get a event ', e.clientID,' from ',e.type
    
if __name__=='__main__':
  test()

    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -