日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
使用Python和Asyncio編寫在線多人游戲(一)

你在 Python 中用過異步編程嗎?本文中我會(huì)告訴你怎樣做,而且用一個(gè)能工作的例子來(lái)展示它:這是一個(gè)流行的貪吃蛇游戲,而且是為多人游戲而設(shè)計(jì)的。

  • 游戲入口在此,點(diǎn)此體驗(yàn)。

1、簡(jiǎn)介

在技術(shù)和文化領(lǐng)域,大規(guī)模多人在線游戲(MMO)毋庸置疑是我們當(dāng)今世界的潮流之一。很長(zhǎng)時(shí)間以來(lái),為一個(gè) MMO 游戲?qū)懸粋€(gè)服務(wù)器這件事總是會(huì)涉及到大量的預(yù)算與復(fù)雜的底層編程技術(shù),不過在最近這幾年,事情迅速發(fā)生了變化?;趧?dòng)態(tài)語(yǔ)言的現(xiàn)代框架允許在中檔的硬件上面處理大量并發(fā)的用戶連接。同時(shí),HTML5 和 WebSockets 標(biāo)準(zhǔn)使得創(chuàng)建基于實(shí)時(shí)圖形的游戲的直接運(yùn)行至瀏覽器上的客戶端成為可能,而不需要任何的擴(kuò)展。

對(duì)于創(chuàng)建可擴(kuò)展的非堵塞性的服務(wù)器來(lái)說(shuō),Python 可能不是***的工具,尤其是和在這個(gè)領(lǐng)域里***的 Node.js 相比而言。但是最近版本的 Python 正在改變這種現(xiàn)狀。asyncio 的引入和一個(gè)特別的 async/await 語(yǔ)法使得異步代碼看起來(lái)像常規(guī)的阻塞代碼一樣,這使得 Python 成為了一個(gè)值得信賴的異步編程語(yǔ)言,所以我將嘗試?yán)眠@些新特點(diǎn)來(lái)創(chuàng)建一個(gè)多人在線游戲。

2、異步

一個(gè)游戲服務(wù)器應(yīng)該可以接受盡可能多的用戶并發(fā)連接,并實(shí)時(shí)處理這些連接。一個(gè)典型的解決方案是創(chuàng)建線程,然而在這種情況下并不能解決這個(gè)問題。運(yùn)行上千的線程需要 CPU 在它們之間不停的切換(這叫做上下文切換),這將導(dǎo)致開銷非常大,效率很低下。更糟糕的是使用進(jìn)程來(lái)實(shí)現(xiàn),因?yàn)?,不但如此,它們還會(huì)占用大量的內(nèi)存。在 Python 中,甚至還有一個(gè)問題,Python 的解釋器(CPython)并不是針對(duì)多線程設(shè)計(jì)的,相反它主要針對(duì)于單線程應(yīng)用實(shí)現(xiàn)***的性能。這就是為什么它使用 GIL(global interpreter lock),這是一個(gè)不允許同時(shí)運(yùn)行多線程 Python 代碼的架構(gòu),以防止同一個(gè)共享對(duì)象出現(xiàn)使用不可控。正常情況下,在當(dāng)前線程正在等待的時(shí)候,解釋器會(huì)轉(zhuǎn)換到另一個(gè)線程,通常是等待一個(gè) I/O 的響應(yīng)(舉例說(shuō),比如等待 Web 服務(wù)器的響應(yīng))。這就允許在你的應(yīng)用中實(shí)現(xiàn)非阻塞 I/O 操作,因?yàn)槊恳粋€(gè)操作僅僅阻塞一個(gè)線程而不是阻塞整個(gè)服務(wù)器。然而,這也使得通常的多線程方案變得幾近無(wú)用,因?yàn)樗辉试S你并發(fā)執(zhí)行 Python 代碼,即使是在多核心的 CPU 上也是這樣。而與此同時(shí),在一個(gè)單一線程中擁有非阻塞 I/O 是完全有可能的,因而消除了經(jīng)常切換上下文的需要。

實(shí)際上,你可以用純 Python 代碼來(lái)實(shí)現(xiàn)一個(gè)單線程的非阻塞 I/O。你所需要的只是標(biāo)準(zhǔn)的 select 模塊,這個(gè)模塊可以讓你寫一個(gè)事件循環(huán)來(lái)等待未阻塞的 socket 的 I/O。然而,這個(gè)方法需要你在一個(gè)地方定義所有 app 的邏輯,用不了多久,你的 app 就會(huì)變成非常復(fù)雜的狀態(tài)機(jī)。有一些框架可以簡(jiǎn)化這個(gè)任務(wù),比較流行的是 tornade 和 twisted。它們被用來(lái)使用回調(diào)方法實(shí)現(xiàn)復(fù)雜的協(xié)議(這和 Node.js 比較相似)。這種框架運(yùn)行在它自己的事件循環(huán)中,按照定義的事件調(diào)用你的回調(diào)函數(shù)。并且,這或許是一些情況的解決方案,但是它仍然需要使用回調(diào)的方式編程,這使你的代碼變得碎片化。與寫同步代碼并且并發(fā)地執(zhí)行多個(gè)副本相比,這就像我們?cè)谄胀ǖ木€程上做的一樣。在單個(gè)線程上這為什么是不可能的呢?

這就是為什么出現(xiàn)微線程(microthread)概念的原因。這個(gè)想法是為了在一個(gè)線程上并發(fā)執(zhí)行任務(wù)。當(dāng)你在一個(gè)任務(wù)中調(diào)用阻塞的方法時(shí),有一個(gè)叫做“manager” (或者“scheduler”)的東西在執(zhí)行事件循環(huán)。當(dāng)有一些事件準(zhǔn)備處理的時(shí)候,一個(gè) manager 會(huì)轉(zhuǎn)移執(zhí)行權(quán)給一個(gè)任務(wù),并等著它執(zhí)行完畢。任務(wù)將一直執(zhí)行,直到它遇到一個(gè)阻塞調(diào)用,然后它就會(huì)將執(zhí)行權(quán)返還給 manager。

微線程也稱為輕量級(jí)線程(lightweight threads)或綠色線程(green threads)(來(lái)自于 Java 中的一個(gè)術(shù)語(yǔ))。在偽線程中并發(fā)執(zhí)行的任務(wù)叫做 tasklets、greenlets 或者協(xié)程(coroutines)。

Python 中的微線程最早的實(shí)現(xiàn)之一是 Stackless Python。它之所以這么知名是因?yàn)樗挥迷诹艘粋€(gè)叫 EVE online 的非常有名的在線游戲中。這個(gè) MMO 游戲自稱說(shuō)在一個(gè)持久的“宇宙”中,有上千個(gè)玩家在做不同的活動(dòng),這些都是實(shí)時(shí)發(fā)生的。Stackless 是一個(gè)獨(dú)立的 Python 解釋器,它代替了標(biāo)準(zhǔn)的函數(shù)棧調(diào)用,并且直接控制程序運(yùn)行流程來(lái)減少上下文切換的開銷。盡管這非常有效,這個(gè)解決方案不如在標(biāo)準(zhǔn)解釋器中使用“軟”庫(kù)更流行,像 eventlet 和 gevent 的軟件包配備了修補(bǔ)過的標(biāo)準(zhǔn) I/O 庫(kù),I/O 函數(shù)會(huì)將執(zhí)行權(quán)傳遞到內(nèi)部事件循環(huán)。這使得將正常的阻塞代碼轉(zhuǎn)變成非阻塞的代碼變得簡(jiǎn)單。這種方法的一個(gè)缺點(diǎn)是從代碼上看這并不分明,它的調(diào)用是非阻塞的。新版本的 Python 引入了本地協(xié)程作為生成器的高級(jí)形式。在 Python 的 3.4 版本之后,引入了 asyncio 庫(kù),這個(gè)庫(kù)依賴于本地協(xié)程來(lái)提供單線程并發(fā)。但是僅僅到了 Python 3.5 ,協(xié)程就變成了 Python 語(yǔ)言的一部分,使用新的關(guān)鍵字 async 和 await 來(lái)描述。這是一個(gè)簡(jiǎn)單的例子,演示了使用 asyncio 來(lái)運(yùn)行并發(fā)任務(wù)。

 
 
  1. import asyncio 
  2. async def my_task(seconds): 
  3.     print("start sleeping for {} seconds".format(seconds)) 
  4.     await asyncio.sleep(seconds) 
  5.     print("end sleeping for {} seconds".format(seconds)) 
  6. all_tasks = asyncio.gather(my_task(1), my_task(2)) 
  7. loop = asyncio.get_event_loop() 
  8. loop.run_until_complete(all_tasks) 
  9. loop.close()     

我們啟動(dòng)了兩個(gè)任務(wù),一個(gè)睡眠 1 秒鐘,另一個(gè)睡眠 2 秒鐘,輸出如下:

 
 
  1. start sleeping for 1 seconds 
  2. start sleeping for 2 seconds 
  3. end sleeping for 1 seconds 
  4. end sleeping for 2 seconds 

正如你所看到的,協(xié)程不會(huì)阻塞彼此——第二個(gè)任務(wù)在***個(gè)結(jié)束之前啟動(dòng)。這發(fā)生的原因是 asyncio.sleep 是協(xié)程,它會(huì)返回執(zhí)行權(quán)給調(diào)度器,直到時(shí)間到了。

在下一節(jié)中,我們將會(huì)使用基于協(xié)程的任務(wù)來(lái)創(chuàng)建一個(gè)游戲循環(huán)。

  • 使用Python和Asyncio編寫在線多人游戲(二)
  • 使用Python和Asyncio編寫在線多人游戲(三)

分享名稱:使用Python和Asyncio編寫在線多人游戲(一)
標(biāo)題網(wǎng)址:http://www.5511xx.com/article/cdhejoc.html