这篇文章本来是我发在9秒论坛的一篇文章,但前几天发现因为论坛改版,原版文章已经不能正常访问,附件也不能下载了,所以决定在自己的博客重新写一次,并且针对上次文章的反馈稍微修改下,因为上次,有人用按我文章的内容搭建之后,发现我文章里面缺了一个小的需要注意的环节,我在交流群里面已经给出了解决方法,所以这次一起写一下,
ubuntu12.04安装,因为我电脑里本来就装了ubuntu12.04虚拟机,所以安装系统就不说了,大家要想自己尝试安装,自己去下个安装镜像,或者写信给开发组,开发组会邮寄一张安装光盘给你的(注:ubuntu没有yum服务,安装命令为apt-getinstall)。
开始安装必要的软件
第一步:gcc安装,Linux下如果不是刚装的系统,这个应该之前都安装好了
我们来查看是否安装gcc
$ gcc –vsersion
如果没有安装那么登陆 【软件中心】
如果找不到【软件中心 】在Dash主页里面的已安装软件里找,在软件中心搜索栏里搜索gcc,或者打开终端(找不到的话,同样去Dash主页里面的已安装软件里找),在终端里面敲入
$ sudo apt-get build-depgcc,装完我们进行下一步mysql安装
Mysql跟gcc一样,我们都在【软件中⼼】安装,终端安装命令为sudo apt-get installmysql-server
服务端安装好后,根据自己的喜好来安装客户端软件,我个人喜欢Mysqlnavigator 功能很强大,操作也比较简单,跟使用windows下的软件很相似。在【软件中⼼】里面直接可以找到安装。
python 安装
还是登陆 【软件中心】搜索框内输入 python会出现python2.7 可以直接进行安装
easy_install 安装
终端下
swordfishx@swordfishx-virtual-machine:~$ sudo apt-get install python-setuptools
[sudo] password for swordfishx:
apt-get install libmysqld-dev
apt-get install libmysqlclient-dev
sudo apt-get install python-dev
如果遇到mysql开发版的问题,上面的几个安装会解决问题。如果没有遇到问题,那就继续。
下面安装protobuf 安装
.下载https://code.google.com/p/protobuf/downloads/list
解压并安装解压命令
tar zxvf protobuf-2.5.0.tar.bz2或者右键解压
然后
tar zxvf protobuf-2.5.0.tar.bz2或者右键解压
然后
cd protobuf-2.5.0 //进入安装目录
./configure //文件安装配置
make && make install //安装
libevent 安装一样
.下载http://libevent.org/
.解压安装
tar zxvf libevent-2.0.21-stable.tar.gz
cd libevent-2.0.21-stable
./configure --prefix=/usr //稍有不同
make && make install
memacached安装
终端直接输入(不要自己下载memcached编译安装,不知什么原因,编译不成功,不要给自己找麻烦)
sudoapt-get install memcached
安装之后
键入memcached -d -m 128 -p 11211 -u root
开启服务,服务命令参数为
{
-p 监听的端口
-l 连接的 IP地址, 默认是本机
-d start 启动 memcached 服务
-d restart 重起 memcached 服务
-d stop|shutdown 关闭正在运行的 memcached 服务
-d install 安装 memcached 服务
-d uninstall 卸载 memcached 服务
-u 以的身份运行 (仅在以 root运行的时候有效)
-m 最大内存使用,单位 MB。默认 64MB
-M 内存耗尽时返回错误,而不是删除项
-c 最大同时连接数,默认是 1024
-f 块大小增长因子,默认是 1.25
-n 最小分配空间,key+value+flags 默认是 48
-h 显示帮助
}
新开个终端窗口
telnet 127.0.0.1 11211 之后键入stats命令可以查看当前看缓存服务的状态
具体操作
swordfishx@swordfishx-virtual-machine:~$ telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'. //说明监控成功,之后输入stats
stats
STAT pid 534
STAT uptime 96
STAT time 1392961141
STAT version 1.4.13
STAT libevent 2.0.21-stable
STAT pointer_size 32
STAT rusage_user 0.008000
STAT rusage_system 0.000000
STAT curr_connections 5
STAT total_connections 6
STAT connection_structures 6
STAT reserved_fds 20
STAT cmd_get 0
STAT cmd_set 0
STAT cmd_flush 0
STAT cmd_touch 0
STAT get_hits 0
STAT get_misses 0
STAT delete_misses 0
STAT delete_hits 0
STAT incr_misses 0
STAT incr_hits 0
STAT decr_misses 0
STAT decr_hits 0
STAT cas_misses 0
STAT cas_hits 0
STAT cas_badval 0
STAT touch_hits 0
STAT touch_misses 0
STAT auth_cmds 0
STAT auth_errors 0
STAT bytes_read 7
STAT bytes_written 0
STAT limit_maxbytes 67108864
STAT accepting_conns 1
STAT listen_disabled_num 0
STAT threads 4
STAT conn_yields 0
STAT hash_power_level 16
STAT hash_bytes 262144
STAT hash_is_expanding 0
STAT expired_unfetched 0
STAT evicted_unfetched 0
STAT bytes 0
STAT curr_items 0
STAT total_items 0
STAT evictions 0
STAT reclaimed 0
END
^]quit //退出命令,上面就是memcached运行的状态
---------------------------------------------------
memcached 服务器的功能呢,是生成一个虚拟的数据库,因为这个临时数据库存在在内存中,所以读写速度大大加快,隔一段时间
memcached会把内存里的临时数据更新进数据库。
到现在我们工作完成了大半了
下面我们安装第三方库
Sudo easy_install twisted
Sudo easy_install python-memcached
Sudo easy_install DBUtils
Sudo easy_install zope.interface
Sudo easy_install affinity
Sudo easy_install MySQL-python
Firefly 安装
http://www.9miao.com/thread-44805-1-1.html下载
2.解压之后
Cd 安装目录
python setup.py build
python setup.py install
测试是否安装成功
swordfishx@swordfishx-virtual-machine:~$ firefly-admin.py createproject FireflyHelloWorld
create dir FireflyHelloWorld
create success //说明可以创建
swordfishx@swordfishx-virtual-machine:~$ cd FireflyHelloWorld
swordfishx@swordfishx-virtual-machine:~/FireflyHelloWorld$ ls
app appmain.py config.json startmaster.py tool
swordfishx@swordfishx-virtual-machine:~/FireflyHelloWorld$ python startmaster.py
2014-02-21 14:16:13+0800 [-] Log opened.
2014-02-21 14:16:13+0800 [-] DelaySite starting on 9998
2014-02-21 14:16:13+0800 [-] Starting factory
<firefly.web.delayrequest.DelaySite instance at 0x8c7014c>
2014-02-21 14:16:13+0800 [-] BilateralFactory starting on 9999
2014-02-21 14:16:13+0800 [-] Starting factory
<firefly.distributed.root.BilateralFactory instance at 0x8c706ec>
2014-02-21 14:16:14+0800 [-] Log opened.
2014-02-21 14:16:14+0800 [-] gate start...
2014-02-21 14:16:14+0800 [-] Log opened.
2014-02-21 14:16:14+0800 [-] net start...
2014-02-21 14:16:14+0800 [-] gate pid: 2186
2014-02-21 14:16:14+0800 [-] net pid: 2187
2014-02-21 14:16:14+0800 [BilateralBroker,1,127.0.0.1] node [gate]
takeProxy ready
好了这样,我们的firefly就安装完了。
firefly安装好了,我们就拿个官方的通信例子测试一下
首先看下json配置文件都都代表什么
配置中主要包括四个部分,master,servers,db,memcached。master 用来
定义master 的端口,servers 用来定义各个服务器中的配置,以及服务进程的
扩展。db定义了数据库的连接配置信息,memcached配置 memcached服务
的连接配置信息。
master 配置
rootport master 服务的管理端口;
webport master 服务的对外http端口,通过web接口实现对各个服务进
程的管理。
servers 配置
server 下面配置的没一个key 的名称就是定义的新的服务进程的名称。通过
添加新的项来扩充服务进程。每个服务进程的配置规则如下:
netport[可选]提供客户端进行tcp连接的端口,用户与客户端的通信。
rootport[可选]提供其他服务进程连接的端口,这样实现进程间的RPC 调用
rootname要连接到的服务进程的名称,rootport要连接到的服务进程的端口。
name[可选]服务进程的名称
app[可选]指定该进程的入口模块名称
log[可选]指定该进程的日志文件存放信息
db[可选]是否需要数据库服务
mem[可选]是否需要memcached缓存服务
cpu[可选]进程绑定到指定 cpu核心运行,减少 cpu 切换的性能消耗
db 配置[可选]
host 数据库服务地址
user 数据库用户名
passwd 数据库密码
port 数据库连接端口
db 数据库库名称
charset 数据库连接客户端编码
memcached 配置[可选]
urls memcache连接配置
hostname memcached缓存分配命名。
本例演示的是 firefly 完整通讯,客户端→net(客户端连接)服务器→gate(场景跳转,
消息分发)服务器→game(游戏场景,逻辑)服务器。客户端将用户输入的数字发送到服
务器,服务器随机一个数进行对比,一样则返回 True,不一样则返回 False 和服务器随机的
数值。
1.创建工程
命令行下输入 firefly-admin.py createproject test_netconnect-distributed(linux 在终端输入,这里测试在win平台),
{
"master":{"rootport":9999,"webport":9998},
"servers":{
"net":{"netport":11000,"name":"net","app":"app.net","remoteport":[{"rootport":10001,"rootname":"gate"}]},
"gate":{"rootport":10001,"name":"gate","app":"app.gate"},
"game":{"remoteport":[{"rootport":10001,"rootname":"gate"}],"name":"game","app":"app.game"}
},
"db":{
"host":"localhost",
"user":"root",
"passwd":"111",
"port":3306,
"db":"test",
"charset":"utf8"
}
}
C:\Users\Administrator>d:
D:\>cd D:\test_netconnect-distributed
D:\test_netconnect-distributed>python D:\test_netconnect-distributed\startmaster
.py
2015-06-06 14:59:56+0800 [-] Log opened.
2015-06-06 14:59:56+0800 [-] DelaySite starting on 9998
2015-06-06 14:59:56+0800 [-] Starting factory <firefly.web.delayrequest.DelaySit
e instance at 0x0000000002E93F48>
2015-06-06 14:59:56+0800 [-] BilateralFactory starting on 9999
2015-06-06 14:59:56+0800 [-] Starting factory <firefly.distributed.root.Bilatera
lFactory instance at 0x0000000002EA04C8>
2015-06-06 14:59:58+0800 [-] Log opened.
2015-06-06 14:59:58+0800 [-] Log opened.
2015-06-06 14:59:58+0800 [-] Log opened.
2015-06-06 14:59:58+0800 [-] game start...
22015-06-06 14:59:58+0800 [-] net start...
2015-06-06 14:59:58+0800 [-] gate start...
015-06-06 14:59:58+0800 [-] game pid: 8864
22015-06-06 14:59:58+0800 [-] net pid: 6460
015-06-06 14:59:58+0800 [-] gate pid: 9140
2015-06-06 14:59:58+0800 [BilateralBroker,0,127.0.0.1] node [net] takeProxy read
y
2015-06-06 14:59:58+0800 [BilateralBroker,1,127.0.0.1] node [game] takeProxy rea
dy
2015-06-06 14:59:58+0800 [BilateralBroker,2,127.0.0.1] node [gate] takeProxy rea
dy
22015-06-06 14:59:58+0800 [Broker,client] call method remote_connect on service[
single]
015-06-06 14:59:58+0800 [Broker,client] call method remote_connect on service[si
ngle]
22015-06-06 14:59:58+0800 [Broker,client] Starting factory <twisted.spread.pb.PB
ClientFactory instance at 0x0000000003019B88>
015-06-06 14:59:58+0800 [Broker,client] Starting factory <twisted.spread.pb.PBCl
ientFactory instance at 0x0000000002F5F088>
2015-06-06 14:59:58+0800 [BilateralBroker,0,127.0.0.1] node [game] takeProxy rea
dy
2015-06-06 14:59:58+0800 [BilateralBroker,1,127.0.0.1] node [net] takeProxy read
y
2)运行客户端,输入 1~10 中任意一个数字,输入 exit 退出客户端
在客户端控制台输入
看看代码
net.py
#coding:utf8
from firefly.server.globalobject import netserviceHandle,GlobalObject
@netserviceHandle
def random_1001(_conn,number):
#客户端传来的number是str型,转换成int型
number = int(number)
#调用root服务器(gate)的random_1002方法,参数为number
result = GlobalObject().remote['gate'].callRemote("random_1002",number)
#返回结果
return result
gate.py
#coding:utf8
from firefly.server.globalobject import rootserviceHandle,GlobalObject
@rootserviceHandle
def random_1002(number):
#调用node服务器(game)的random_1003方法,参数为number
result = GlobalObject().root.callChildByName("game","random_1003",number)
#返回结果
return result
game.py
#coding:utf8
from firefly.server.globalobject import remoteserviceHandle
import random
@remoteserviceHandle("gate")
def random_1003(number):
randomNu = random.randint(1,10)#在1~10内随机一个数
if number == randomNu:#对比客户端传来的数据
return "True"
else:
return "False,result is %s" % randomNu
客户端
#coding:utf8
from socket import AF_INET,SOCK_STREAM,socket
import struct,time
def sendData(sendstr,commandId):
'''定义协议头
'''
HEAD_0 = chr(0)
HEAD_1 = chr(0)
HEAD_2 = chr(0)
HEAD_3 = chr(0)
ProtoVersion = chr(0)
ServerVersion = 0
sendstr = sendstr
data = struct.pack('!sssss3I',HEAD_0,HEAD_1,HEAD_2,\
HEAD_3,ProtoVersion,ServerVersion,\
len(sendstr)+4,commandId)
senddata = data+sendstr
return senddata
def resolveRecvdata(data):
'''解析数据,根据定义的协议头解析服务器返回的数据
'''
head = struct.unpack('!sssss3I',data[:17])
lenght = head[6]
message = data[17:17+lenght]
return message
if __name__ == "__main__":
HOST='localhost'
PORT=11000
ADDR=(HOST , PORT)
client = socket(AF_INET,SOCK_STREAM)
client.connect(ADDR)#建立socket连接
while 1:
number = raw_input("Please enter your number(1~10):")
if number == "exit":
break
client.sendall(sendData(number,1001))#向服务器发送消息
message = client.recv(1024)#接收服务器返回的消息
message = resolveRecvdata(message)#解析消息
print message
client.close()