- 百万在线:大型游戏服务端开发
- 罗培羽
- 1953字
- 2021-09-17 17:04:57
2.6 做留言板,使用数据库
游戏服务端的另一项重要功能是保存玩家数据,Skynet提供了操作MySQL数据库、MongoDB数据库的模块。
2.6.1 功能需求
如图2-18所示,客户端发送“set XXX”命令时,程序会把留言“XXX”存入数据库,发送“get”命令时,程序会把整个留言板返回给客户端。
图2-18 留言板示意图
2.6.2 学习数据库模块
skynet.db.mysql模块提供操作MySQL数据库的方法,如表2-7所示。
表2-7 连接MySQL数据库的API
2.6.3 准备数据库
服务端与MySQL通过TCP相连,获取数据时,服务端会以特定形式发送形如“查询id为101的玩家数据”的消息,MySQL收到消息后,回应查到的数据。启动留言板程序前,需要先开启MySQL数据库,预先创建数据表。
知识拓展:完整地安装和启动MySQL数据库包括如下步骤:
(1)安装MySQL数据库
在CentOS下执行如下三条指令,下载MySQL5.7并安装它。如果提示系统找不到wget或rpm,请先用yum install XXX安装它们。
wget 'https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm' rpm -Uvh mysql57-community-release-el7-11.noarch.rpm yum install mysql-community-server
(2)启动MySQL数据库
执行如下指令启动MySQL数据库。
service mysqld start
(3)查看默认数据库密码
新版MySQL(5.7之后)出于安全考虑,要求用户重设密码,之后才能正常操作。要重设密码,就要先登录数据库,再执行修改密码的指令。要登录数据库,就得用默认的密码。那么,默认的密码是什么?执行如下指令打开MySQL的日志文件。
vim/var/log/mysqld.log
会看到其中有一句
A temporary password is generated for root@localhost: qeWupq-Bp4K5
其中的“qeWupq-Bp4K5”就是首次登录时要输入的密码,这是个随机数,先记下它。
(4)修改密码
输入如下指令登录数据库,其中-u后面的root代表用户名,-p后面的字符代表初始密码。
mysql -h127.0.0.1 -uroot -pqeWupq-Bp4K5
在MySQL的命令行中输入如下指令,其中的12345678aB-代表新密码。密码必须是8位以上,且含有数字、字母和特殊字符。
mysql> alter user 'root'@'localhost' identified by "12345678aB-";
(5)开放权限
出于安全考虑,默认情况下,新版MySQL只开放本地root权限,即只能在本机登录。由于我们只是做实验,不需要考虑安全性问题,因此可以输入如下语句,让其他电脑连接(安全的做法是新建一些受限账号,对这些账号仅开放所需的权限)。
mysql> use mysql; mysql> update user set host='%' where user='root'; mysql> flush privileges;
(6)测试
重新连接数据库,输入如下SQL语句显示MySQL数据库中的库。如能成功,说明一切就绪。
mysql> show databases;
图2-19展示了MySQL数据库的结构。一个MySQL包含多个库,库中包含多个表,每个表包含多个栏位。操作数据库时,需选定某个库(如表2-5中mysql.connect的database项),再增删改表中的数据。
图2-19 MySQL数据库的结构
知识拓展:有多种手动操作MySQL数据库的方法。
(1)用命令行操作
使用“mysql-h127.0.0.1-uroot-pXXX”登录数据库,再输入SQL语句即可实现操作,只是不太直观。
(2)用工具操作
可在Windows上安装“Navicat for MySQL”来操作MySQL数据库,它是个可视化的MySQL客户端软件。本节会演示“Navicat for MySQL”的操作方法。
先创建名为message_board的库。如图2-20所示,打开Navicat,填入MySQL数据库的IP、端口、用户名和密码,登录数据库(如果连接失败,除了检查用户名、密码外,还需设置云服务器的安全策略,开放3306端口)。
图2-20 用Navicat连接数据库
右键单击连接名,选择“新建数据库”,命名为“message_board”。选择新创建的数据库,创建名为“msgs”的表,表结构如图2-21所示。msgs表包含id和text两个栏位。id栏位为int类型,将其设置为主键,不允许空值,并勾选自动递增;text栏位设为text类型。
图2-21 msgs表结构
在msgs表里添加几条数据(用于测试),如图2-22所示。
图2-22 在msgs表里添加测试数据
2.6.4 代码实现
这里先不直接做留言板,而是写个小程序尝试测试数据库读写功能,以便融会贯通。编写代码2-8所示的主服务,功能如下:
·调用mysql.connect连接MySQL,并选用message_board库。
·使用db:query("insert ...")向数据库插入一条数据,在text栏位插入字符串“hehe”。
·使用db:query("select ...")查询数据库,将结果保存到res中,遍历它并打印出来。
代码2-8 examples/Pmain.lua
(资源:Chapter2/5_mysql.lua)
local skynet = require "skynet"skynet.start(function() --连接 local ({ host="39.100.116.101", port=3306, database="message_board", user="root", password="7a77-788b889aB", max_packet_size = 1024 * 1024, on_connect = nil }) --插入 local res = ("insert into msgs (text) values (\'hehe\')") --查询 res = ("select * from msgs") --打印 for i,v in pairs(res) do print ( i," ",v.id, " ",v.text) end end)
运行服务端,能看到如图2-23所示的输出,其中“hello”和“good”是手动添加的数据,“hehe”是主服务添加的数据。
图2-23 程序运行结果
现在将网络编程和数据库操作结合起来,完成本节的需求。在代码2-9中,新增变量db用于保存数据库对象;服务启动后,开启网络监听,并发起数据库连接。
代码2-9 examples/Pmain.lua中的部分内容
(资源:Chapter2/5_messageboard.lua)
local skynet = require "skynet" local socket = require "skynet.socket" local mysql = require "skynet.db.mysql" local db = nil skynet.start(function() --网络监听 local listenfd = socket.listen("0.0.0.0", 8888) socket.start(listenfd ,connect) --连接数据库 db=mysql.connect({ host="127.0.0.1", port=3306, database="message_board", user="root", password="12345678aB+", max_packet_size = 1024 * 1024, on_connect = nil }) end)
新连接的回调方法connect如代码2-10所示,它分成两个部分:
·如果客户端发送的数据是“get\r\n”,则查询数据库,然后将结果一条条地发回。
·如果客户端发送的是“set XXX”(为了简洁,假设用户会输入正确的数据),则用正则表达式将字符串XXX提取出来(变量data),然后插入数据库中。
代码2-10 examples/Pmain.lua中connect方法的部分代码
function connect(fd, addr) …… --正常接收 if readdata ~= nil then --返回留言板内容 if readdata == "get\r\n" then local res = db:query("select * from msgs") for i,v in pairs(res) do socket.write (fd, v.id.." "..v.text.."\r\n") end --留言 else local data = string.match( readdata, "set (.-)\r\n") db:query("insert into msgs (text) values (\'"..data.."\')") end …… end
说明:“\r\n”即换行符,在telnet中输入字符串,它会把换行符也发给服务端。
2.6.5 运行结果
开启服务端,再用telnet连接。客户端的运行结果如图2-24所示:输入get命令,能看到所有留言;输入set lpy表示插入留言;再输入get可获取相应信息。
图2-24 留言板客户端的运行结果