#!/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()