- 百萬在線:大型游戲服務端開發
- 羅培羽
- 1953字
- 2021-09-17 17:04:56
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 留言板客戶端的運行結果
- Go Web編程
- Delphi程序設計基礎:教程、實驗、習題
- SoapUI Cookbook
- Java Web基礎與實例教程(第2版·微課版)
- Python零基礎快樂學習之旅(K12實戰訓練)
- 精通API架構:設計、運維與演進
- Effective Python Penetration Testing
- 你不知道的JavaScript(中卷)
- 微信小程序開發解析
- Hands-On Automation Testing with Java for Beginners
- Scratch3.0趣味編程動手玩:比賽訓練營
- Python爬蟲、數據分析與可視化:工具詳解與案例實戰
- Vue.js 3應用開發與核心源碼解析
- Keil Cx51 V7.0單片機高級語言編程與μVision2應用實踐
- Java程序設計入門(第2版)