程序作品(2)——坦克動蕩(聯(lián)機版)(重制版)

籌劃
閱讀過我之前的文章的讀者們都知道,坦克動蕩是一款刺激的雙人射擊游戲。為了提升游戲體驗,我在去年制作了該游戲的聯(lián)機版本。但是這個聯(lián)機版本有許多問題,包括但不限于只能在同一局域網(wǎng)下聯(lián)機、代碼可讀性和可維護性差、運行效率低下等等。因此,經(jīng)過了一年的技術(shù)積累,我決定重新寫一遍這個游戲,順便修復一下上面提到的那些問題。
1.?跨局域網(wǎng)連接
使用python的socket庫實現(xiàn)跨局域網(wǎng)連接其實非常簡單。在局域網(wǎng)內(nèi)部連接的前提下,只需要把服務器和客戶端的

改成

即可
(這么簡單的方法我去年在百度上硬是查不到,就無語
1.1 跨局域網(wǎng)連接衍生出的bug
由于跨局域網(wǎng)連接時兩臺電腦處于不同的局域網(wǎng)下,因此信息傳輸就需要經(jīng)過許多路由器和交換機。為了減輕這些交換機的壓力,一臺電腦所發(fā)送的多條信息有可能被打包成一個數(shù)據(jù)包一起發(fā)送,而很長的信息也有可能被切成多個數(shù)據(jù)包分開發(fā)送。
這樣在接受信息的時候,就有可能出現(xiàn)執(zhí)行一次接受命令就接收到對方發(fā)送的多條信息,或者一次接受命令不能完整接受一條信息的情況。這就是粘包問題。
我在當時還不知道粘包問題的存在。因此在調(diào)這段代碼的時候的心理活動大家可以自行腦補一下
解決粘包問題的方法有很多,我在這里使用的是在消息前面注明消息長度,以便在接受的時候把粘在一起的消息拆分開來的方法。
由于在這個程序里發(fā)送的信息都比較短,因此沒有出現(xiàn)將一條長信息拆分成多條信息發(fā)送的情況。但是在下面一篇文章里即將介紹的另一個項目中,就出現(xiàn)了這種情況。因此這個解決方法在下一個項目中還需要進行一點改變
具體的實現(xiàn)方法是這樣的:
在發(fā)送端,每生成一個待發(fā)送的字符串的時候,都求一下這個字符串的長度,并將這個長度放在字符串的開頭
在接收端,首先準備一個列表叫做recv_list。這個列表相當于一個隊列,每次需要接收信息的時候都先檢查一下這個隊列有沒有空,如果沒有空則先從這個隊列里彈出信息來使用,如果空了則執(zhí)行一下接受命令,并把接收到的信息拆開按順序放進這個隊列里,以便下次取用。
2. 服務器
在進行跨局域網(wǎng)連接的時候,我發(fā)現(xiàn)由于某些未知的原因(大概率是因為網(wǎng)關(guān)和防火墻的限制),Windows電腦無法作為服務器連接其它電腦,而Mac則有一定概率可以連接。又由于我使用的檢測鍵盤活動的庫只能在Windows電腦上使用,因此我就無法像我之前那個聯(lián)機版那樣將客戶機用作服務器了。這就意味著我必須單獨寫一個服務器程序來管理多臺客戶機的連接。
服務器和客戶機之間的通信過程大致和之前那個聯(lián)機版一樣。就是將檢測子彈碰撞放在了服務器上,坦克的移動在客戶機上完成,并且服務器要負責同步兩臺客戶機之間的信息。這里不過多贅述
服務器這里唯一的難點就是如何讓一臺服務器同時服務多場比賽。這就需要用到多線程(雖然說我在上一個聯(lián)機版中將多線程用于與客戶機通信,但是我發(fā)現(xiàn)那是完全沒有必要的,反而會增加編程難度)
這里的多線程的邏輯大致是這樣的:
在服務器代碼里定義一個函數(shù),把所有游戲開始之后的代碼都放進去。主程序負責接受客戶機連接,一旦接收到兩個客戶機的連接,就開一個新的線程來執(zhí)行游戲函數(shù),并將那兩個客戶機的連接信息傳進去。
但是不同的操作系統(tǒng)對于多線程傳遞參數(shù)的規(guī)定是不一樣的,像macos和Windows都支持傳遞socket表示連接信息的變量,但是Linux就只能傳遞數(shù)字和字符串等信息。因此當使用Linux系統(tǒng)作為服務器時,多線程的代碼就需要進行一些變化,這些變化在下一個項目中會講到。
總結(jié)
比起上一版的連接程序,這個重制版帶來了非常多的改變,包括可以跨局域網(wǎng)連接,可以一臺服務器服務多場游戲等等。但是跨局域網(wǎng)連接的時候會受到防火墻和網(wǎng)關(guān)的限制,因此沒有保證一定會連接成功,因此我不會開放服務器供大家體驗。不過這個重制版在同一局域網(wǎng)下也可以使用,因此大家如果想體驗的話可以使用自己的電腦作為服務器在同一局域網(wǎng)下與他人游玩。
下期預告:家庭監(jiān)控系統(tǒng)
注:
我已經(jīng)將這個項目的源代碼上傳到百度網(wǎng)盤。點擊“閱讀原文”即可下載
鏈接:https://pan.baidu.com/s/1_4maf_6x0PSyErHEt7TIVQ?pwd=zw48?
提取碼:zw48
從bilibili網(wǎng)頁端復制的文章內(nèi)容會自動帶有作者和出處。請讀者在復制鏈接的時候注意刪除讀者和出處,否則會提示鏈接不存在