游戲之網(wǎng)絡(luò)進階

陷陣之志浴井,有死無生 --趙信

如大家對網(wǎng)絡(luò)還不甚了解,請先參照本系列網(wǎng)絡(luò)介紹博文 游戲之網(wǎng)絡(luò)初篇

現(xiàn)在很少有游戲公司自己用原生Socket API手寫網(wǎng)絡(luò)框架了酪穿,一是增加工作量娱节,增加產(chǎn)品開發(fā)時長税产;二是如果綜合性能摊灭、效率咆贬、高吞吐量、高并發(fā)帚呼,及穩(wěn)健性來說掏缎,自己如果非大神,寫出來的很可能還沒別人已有的網(wǎng)絡(luò)框架好萝挤,自己還需經(jīng)大量測試驗證才能保證線上穩(wěn)定御毅,不容出錯根欧。所以怜珍,現(xiàn)在很多的Java游戲框架,基本上都是用Netty或Mina作為網(wǎng)絡(luò)通信框架的凤粗,Netty和Mina用起來有很多相似之處酥泛,知其一另一個上手就很容易今豆,但在很多人看來,Netty比Mina更好用(更適合游戲使用)柔袁,其一呆躲,Java游戲公司基本都是用Protobuf作為協(xié)議工具的,以應(yīng)對游戲各種功能玩法中前后端所需不同的數(shù)據(jù)字段讀取和傳輸要求捶索,及減少協(xié)議聯(lián)調(diào)出錯幾率插掂,Netty包中自帶對Protobuf的編解碼器,而Mina還需自己去實現(xiàn)Protobuf的編解碼器腥例;其二辅甥,Netty比Mina更好地支持多種協(xié)議,比如對Http的支持燎竖,Netty就比Mina好些璃弄,在《游戲之網(wǎng)絡(luò)初篇》中,游戲常用的協(xié)議Netty都支持构回,簡直為游戲量身打造夏块;其三,Netty比Mina更易使用纤掸,除了Netty自帶很多編解碼器外脐供,在對ByteBuf的操作比Mina的IoBuffer的操作更簡易,此外借跪,Netty支持ByteBuf零拷貝患民,一聽就是讓人省心的提高效率和節(jié)約內(nèi)存的高科技東東。

Netty 和 Mina都為韓國Trustin Lee開發(fā)出來的垦梆,這也是它們很多相似之處的原因之一匹颤。它們都是優(yōu)秀的異步事件驅(qū)動,NIO(非阻塞)網(wǎng)絡(luò)框架托猩,獲得了成百上千的商業(yè)項目驗證印蓖。當(dāng)然,在游戲開發(fā)中京腥,也是錦上添花赦肃。

Protobuf 是谷歌的Protocol Buffers的簡稱,它是一個輕便高效存儲和讀取結(jié)構(gòu)化數(shù)據(jù)的工具公浪,用于結(jié)構(gòu)化數(shù)據(jù)和字節(jié)碼之間互相轉(zhuǎn)換(序列化他宛、反序列化),非常適合用于網(wǎng)絡(luò)傳輸欠气,且支持多種編程語言厅各。游戲中使用Protobuf可以減少協(xié)議聯(lián)調(diào)出錯的幾率,因為一旦使用Protobuf作為協(xié)議工具预柒,當(dāng)定好協(xié)議后队塘,開發(fā)人員只管設(shè)置相應(yīng)字段值即可袁梗,如果擔(dān)心字段漏傳,就用required限定即可憔古;但是如果用其他的協(xié)議工具遮怜,那么開發(fā)人員除了設(shè)置相應(yīng)字段值外,可能還需要正確設(shè)置字段長度鸿市,及字段順序锯梁。

Netty的 ByteBuf 和 Mina的 IoBuffer 都是對JDK的 ByteBuffer 的高級封裝,比起JDK的ByteBuffer焰情,它們都支持動態(tài)擴展(而擴展JDK的ByteBuffer只能新建復(fù)制)涝桅,且修復(fù)了JDK的眾多NIO bug(比自己用原生JDK NIO API更少bug);但是 Mina的IoBuffer和JDK的ByteBuffer都只有一個標(biāo)識位置的指針position烙样,切換讀寫的時候要自己手動調(diào)用flip()和rewind()等冯遂,用起來稍微麻煩,而Netty的ByteBuf使用readerIndex和writerIndex分別維護讀操作和寫操作谒获,實現(xiàn)讀寫索引分離蛤肌,更加直觀。

本文假設(shè)讀者已對Netty有初步的了解批狱,如知道Netty的大致框架(后續(xù)可能會補一些Netty的介紹文章)裸准,了解Netty的核心組件的關(guān)系及其作用,了解消息處理的大致流程赔硫。下面放圖兩張供讀者回憶Netty基本知識點(摘自《Netty實戰(zhàn)》)炒俱,其余需更詳細了解Netty的建議細讀何品翻譯的《Netty實戰(zhàn)》和李林鋒的《Netty權(quán)威指南》,更細節(jié)的需要讀者自己鉆研了爪膊。

netty核心組件.png

Netty核心組件的關(guān)系如下:【

  • 一個 EventLoopGroup 包含一個或者多個 EventLoop权悟;
  • 一個 EventLoop 在它的生命周期內(nèi)只和一個 Thread 綁定;
  • 所有由 EventLoop 處理的 I/O 事件都將在它專有的 Thread 上被處理推盛;
  • 一個 Channel 在它的生命周期內(nèi)只注冊于一個 EventLoop峦阁;
  • 一個 EventLoop 可能會被分配給一個或多個 Channel。
    注意耘成,在這種設(shè)計中榔昔,一個給定 Channel 的 I/O 操作都是由相同的 Thread 執(zhí)行的,實際
    上消除了對于同步的需要瘪菌∪龌幔】

注意上面【】中引用《Netty實戰(zhàn)》的最后一句,即“一個給定 Channel 的 I/O 操作都是由相同的 Thread 執(zhí)行的师妙,實際
上消除了對于同步的需要诵肛。”疆栏,雖然Netty中是這樣曾掂,但在實際游戲開發(fā)中,因為一個EventLoop管理多個Channel壁顶,而每個EventLoop上所有的I/O卻只由一個Thread處理珠洗,這就相當(dāng)于多個客戶端的I/O請求都由一個Thread處理了,這明顯同一時刻可能阻塞其他客戶端了若专,所以在實際游戲開發(fā)中许蓖,每個Channel的I/O操作(即每條協(xié)議請求),都會再放到一個邏輯線程池中處理调衰,這樣避免阻塞其他客戶端膊爪,哎呀,一不小心劇透后面游戲框架博文的內(nèi)容了嚎莉,具體詳情請見后續(xù)框架解讀吧米酬。

netty消息流程.png

以上是I/O操作的流程示意圖,實際中ChannelPipeline中的入站和出站handler都是類似如下添加的

bootstrap.handler(new ChannelInitializer<ServerSocketChannel>() {
            @Override
            protected void initChannel(ServerSocketChannel ch) throws Exception {
                ChannelPipeline pipeline = ch.pipeline();
                pipeline.addLast("http_codec", new HttpClientCodec());
                pipeline.addLast("http_aggregator", new HttpObjectAggregator(65536));
                pipeline.addLast("protobuf_decoder", new ProtoDecoder(null, 5120));
                pipeline.addLast("server_handler", new ProtoServerHandler());
                pipeline.addLast("protobuf_encoder", new ProtoEncoder(checkSum, 2048));
            }
});

本文的原來標(biāo)題是《Netty+Protobuf實現(xiàn)游戲的TCP通信》趋箩,本來是想一篇文章即介紹完這個話題的赃额,但發(fā)現(xiàn)因為想引入Netty和Protobuf的簡介導(dǎo)致文章太長了,不簡介又擔(dān)心新手讀者沒有個承上啟下的因果關(guān)系導(dǎo)致強行去理解Netty和Protobuf實現(xiàn)TCP通信顯得略為僵硬叫确,所以本文標(biāo)題還是改為《游戲之網(wǎng)絡(luò)進階》算了跳芳,旨在對游戲中使用Netty和Protobuf有個大致的介紹,而實際上Netty的內(nèi)容還遠不止本文剛說的那一丁點竹勉,想想李林鋒大神那兩本Netty的書就知道了飞盆,希望讀者能自己去鉆研細讀,廣思集益次乓,從而對游戲的網(wǎng)絡(luò)框架有更好的了解吓歇。

通常,了解一個大眾使用的框架的規(guī)則票腰,比自己手寫類似功能更為迅捷和靠譜照瘾,在現(xiàn)在快節(jié)奏的游戲更新迭代中,快速開發(fā)一款游戲成為節(jié)約成本丧慈,取得市場先手優(yōu)勢的先決條件析命。但這并不鼓勵只是一味的“拿來主義”而不推崇自己的主觀動手能力了,實際的技術(shù)沉淀還需我們自己不斷拓展加深逃默,說不定哪天一個很好的框架就出自這樣動手能力極強的讀者手中了鹃愤。下篇博文可真正進入《Netty+Protobuf實現(xiàn)游戲的TCP通信》了,敬請閱讀完域。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末软吐,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子吟税,更是在濱河造成了極大的恐慌凹耙,老刑警劉巖姿现,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異肖抱,居然都是意外死亡备典,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門意述,熙熙樓的掌柜王于貴愁眉苦臉地迎上來提佣,“玉大人,你說我怎么就攤上這事荤崇“杵粒” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵术荤,是天一觀的道長倚喂。 經(jīng)常有香客問我,道長瓣戚,這世上最難降的妖魔是什么务唐? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮带兜,結(jié)果婚禮上枫笛,老公的妹妹穿的比我還像新娘。我一直安慰自己刚照,他們只是感情好刑巧,可當(dāng)我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著无畔,像睡著了一般啊楚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上浑彰,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天恭理,我揣著相機與錄音,去河邊找鬼郭变。 笑死颜价,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的诉濒。 我是一名探鬼主播周伦,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼未荒!你這毒婦竟也來了专挪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎寨腔,沒想到半個月后速侈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡迫卢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年倚搬,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片靖避。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡潭枣,死狀恐怖比默,靈堂內(nèi)的尸體忽然破棺而出幻捏,到底是詐尸還是另有隱情,我是刑警寧澤命咐,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布篡九,位于F島的核電站,受9級特大地震影響醋奠,放射性物質(zhì)發(fā)生泄漏榛臼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一窜司、第九天 我趴在偏房一處隱蔽的房頂上張望沛善。 院中可真熱鬧,春花似錦塞祈、人聲如沸金刁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽尤蛮。三九已至,卻和暖如春斯议,著一層夾襖步出監(jiān)牢的瞬間产捞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工哼御, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留坯临,地道東北人。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓恋昼,卻偏偏與公主長得像尿扯,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子焰雕,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容