来源:http://ciniao.me/article.php?id=11

---------------

刺鸟原创文章,转载请注明出处
    在之前的准备工作中,我们已经建立了一个socket服务器,并且经过了简单的测试,得到的结论是python可以满足我们的需求,那么接下来,我们要解决的是身为webgame服务端必须的几个功能模块:

一、记录和维护所有客户机的状态
    更新:按照jinmin_lan同学的建议,这里直接用self.transport.sessionno即可,查twisted文档的时候我忽略了这个东西。因此无需按照我下面的方法来手动维护,好吧,我造了一次轮子……    
    为了实现这个功能,我们先回过头来分析下之前的服务端代码:
    1、每个客户端连接会有一个gameSocket对象被创建,然后触发connectionMade事件。
    2、客户端数据到达的时候触发dataReceived事件
    3、连接断开的时候触发connectionLost事件,然后对象被析构

根据通常的处理思路,我们需要为每个客户端建立一个编号,即传说中的sockid,然后维护一个client和sockid之间的双向字典,以便我们能够简单的互相反查。我决定维护2份数据,以空间换时间,新建一个sockMana类来实现该功能:

# sockmana.py
class SockMana:
def __init__ (self):
self.sockNum = 0 #记录当前的在线总数
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服务端代码中import它,并增加调用事件,然后略修改dataReceived事件,当收到客户端数据的时候,我们向客户端返回它的sockid,完整的服务端代码调整为:

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):
#有新用户连接至服务器
def connectionMade(self):
sockMana.addClient(self)
print 'New Client' #客户端断开连接
def connectionLost(self,reason):
sockMana.delClient(self)
print 'Lost Client' #收到客户端发送数据
def dataReceived(self, data):
print 'Get data:' + str(data)
#向该客户端发送数据
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,这样我们就为每个客户端建立了一个唯一且可用于传递和储存的数值编号,在以后的逻辑处理中,这将作为客户端的唯一标识。

好了,我们断开其中一个客户端,看看我们的sockMana工作正常否?

Yes!和预料中的一样,一切工作正常。我们又向前迈进了小小的一步,下面,我们得研究研究服务端如何和客户端之间高效的传输数据了。

#本文由刺鸟原创,欢迎转载,但请保留出处,也欢迎对本文感兴趣的同学多多交流。#

-----

最新文章

  1. mysql 清空表 Truncate及delete区别
  2. 细说webpack之流程篇
  3. 开启SQL Server 2012的远程连接
  4. querySelectorAll
  5. 【Office Web Apps】在 SharePoint 中使用 Office Web Apps
  6. Omi树组件omi-tree编写指南
  7. P1462 通往奥格瑞玛的道路
  8. 使用 TRESTClient 与 TRESTRequest 作为 HTTP Client
  9. Aspose.Words的Merge Field
  10. PAT 1124 Raffle for Weibo Followers
  11. .net core jwt
  12. 分享12款 JavaScript 表格控件(DataGrid)
  13. shiro授权及自定义realm授权(七)
  14. php json中文被转义
  15. PHP 利用redis 做统计缓存mysql的压力
  16. (电工基地笔记)Vivado固化至SPI Flash
  17. Java 开发中的对象拷贝
  18. spring + Mybatis + pageHelper + druid 整合源码分享
  19. DOM操作怎样添加、移除、移动、复制。创建和查找节点?
  20. Druid学习之路 (二)Druid架构

热门文章

  1. 二分求幂 - A^B(王道*)
  2. perl学习笔记——文件测试
  3. Linux学习笔记 (五)关机和重启命令
  4. <十>读<<大话设计模式>>之观察者模式
  5. PowerDesigner 将表的字段name属性设置到comment凝视
  6. lua类库 middleclass学习笔记
  7. python机器学习-逻辑回归
  8. JPA与Hibernate的优缺点
  9. tony_nginx的安装和配置
  10. 自己动手开发更好用的markdown编辑器-05(粘贴上传图片)