刺鳥原創(chuàng)文章,轉(zhuǎn)載請注明出處 在之前的準(zhǔn)備工作中,我們已經(jīng)建立了一個socket服務(wù)器,并且經(jīng)過了簡單的測試,得到的結(jié)論是python可以滿足我們的需求,那么接下來,我們要解決的是身為webgame服務(wù)端必須的幾個功能模塊:
一、記錄和維護(hù)所有客戶機的狀態(tài) 更新:按照jinmin_lan同學(xué)的建議,這里直接用self.transport.sessionno即可,查twisted文檔的時候我忽略了這個東西。因此無需按照我下面的方法來手動維護(hù),好吧,我造了一次輪子……
為了實現(xiàn)這個功能,我們先回過頭來分析下之前的服務(wù)端代碼: 1、每個客戶端連接會有一個gameSocket對象被創(chuàng)建,然后觸發(fā)connectionMade事件。 2、客戶端數(shù)據(jù)到達(dá)的時候觸發(fā)dataReceived事件 3、連接斷開的時候觸發(fā)connectionLost事件,然后對象被析構(gòu)
根據(jù)通常的處理思路,我們需要為每個客戶端建立一個編號,即傳說中的sockid,然后維護(hù)一個client和sockid之間的雙向字典,以便我們能夠簡單的互相反查。我決定維護(hù)2份數(shù)據(jù),以空間換時間,新建一個sockMana類來實現(xiàn)該功能:
- # sockmana.py
- class SockMana:
- def __init__ (self):
- self.sockNum = 0 #記錄當(dāng)前的在線總數(shù)
- self.sockIndex = 1 #累加sockid
- self.client2id = {} #保存client->sockid字典
- self.id2client = {} #保存sockid->client字典
- def addClient(self,client):
- #增加一個客戶端
- print '** add client **'
- self.sockNum = self.sockNum + 1
- self.client2id[client] = self.sockIndex
- self.id2client[self.sockIndex] = client
- self.sockIndex = self.sockIndex + 1
- print self.sockNum
- print self.client2id
- print self.id2client
-
- def delClient(self,client):
- #刪除一個客戶端
- print '** del client **'
- if client in self.client2id:
- self.sockNum = self.sockNum - 1
- _sockid = self.client2id[client]
- del self.client2id[client]
- del self.id2client[_sockid]
- print self.client2id
- print self.id2client
-
- def getSockid(self,client):
- #通過client獲取sockid
- if client in self.client2id:
- return self.client2id[client]
- else:
- return None
-
- def getClient(self,sockid):
- #通過sockid獲取client
- if sockid in self.id2client:
- return self.id2client[sockid]
- else:
- return None
- #初始化連接管理器
- sockMana = SockMana()
接下來在我們的socket服務(wù)端代碼中import它,并增加調(diào)用事件,然后略修改dataReceived事件,當(dāng)收到客戶端數(shù)據(jù)的時候,我們向客戶端返回它的sockid,完整的服務(wù)端代碼調(diào)整為:
- import os
- if os.name!='nt':
- from twisted.internet import epollreactor
- epollreactor.install()
- else:
- from twisted.internet import iocpreactor
- iocpreactor.install()
- from twisted.internet.protocol import Factory,Protocol
- from twisted.internet import reactor
- from sockmana import sockMana
- class gameSocket(Protocol):
- #有新用戶連接至服務(wù)器
- def connectionMade(self):
- sockMana.addClient(self)
- print 'New Client'
-
- #客戶端斷開連接
- def connectionLost(self,reason):
- sockMana.delClient(self)
- print 'Lost Client'
-
- #收到客戶端發(fā)送數(shù)據(jù)
- def dataReceived(self, data):
- print 'Get data:' + str(data)
- #向該客戶端發(fā)送數(shù)據(jù)
- self.transport.write('your sockid is:'+ str(sockMana.getSockid(self)))
-
- if __name__=='__main__':
- f = Factory()
- f.protocol = gameSocket
- reactor.listenTCP(5200,f)
- print 'server started...'
- reactor.run()
然后我們依然用telnet,來建立2個連接試試。
可以看到,每增加一個客戶端,我們的sockMana類中就會分別增加2個 key->val的鍵值對,通過sockMana.getSockid方法即可獲取客戶端的sockid,這樣我們就為每個客戶端建立了一個唯一且可用于傳遞和儲存的數(shù)值編號,在以后的邏輯處理中,這將作為客戶端的唯一標(biāo)識。
好了,我們斷開其中一個客戶端,看看我們的sockMana工作正常否?
Yes!和預(yù)料中的一樣,一切工作正常。我們又向前邁進(jìn)了小小的一步,下面,我們得研究研究服務(wù)端如何和客戶端之間高效的傳輸數(shù)據(jù)了。
|