青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Xiao.Zhu C++

Xiao.Zhu C++

  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
  29 隨筆 :: 14 文章 :: 17 評論 :: 0 Trackbacks
bromon原創 版權所有

  一個多人在線的棋牌類網絡游戲的項目臨近尾聲,我參與了該項目的整個設計流程,并且完成了90%的核心代碼。關于這個項目,有很多地方值得聊一聊。本系列不打算把這個項目將得多么詳細規范,那是設計文檔應該描述的,我打算只說說一些值得注意的地方。這個項目的一個特別之處是,客戶端是手機,用戶通過移動網絡與服務器通信。和PC相比,手機的處理能力極弱,而且網絡流量費用昂貴。因為除了要考慮普通網絡游戲的一些問題之外,這兩點也需要在設計中充分考慮。首先是開發語言的選擇,由于服務器是Linux的環境,MS的技術直接排除,至于MONO嘛,我實在不放心。可供選擇的是C++和Java,Java勝在網絡能力強大,開發周期短,有眾多框架和開源庫的支持,要寫出爛得不可接受的代碼也不容易;C++則勝在速度快。綜合各方面因素,C++更容易把這個項目變成一堆代碼噩夢,我們選擇了Java。

一、             網絡

  網絡游戲,首先面臨的問題當然是如何進行網絡通信。首先考慮的是HTTP協議,因為所有的J2ME手機都支持這個,我們當然想盡可能的兼容用戶。而且HTTP協議封裝程度已經非常高了,不用去考慮線程、同步、狀態管理、連接池,不過HTTP協議有兩個不爽的地方:

  ◇  協議無狀態,這個問題已經困擾過很多人很多次了。我曾考慮過的解決辦法是改造HTTP協議,在數據傳輸完成之后不關閉socket,但是這樣做工作量非常大,在項目周期中,基本上就是Mission impossible,不予考慮。那么客戶也就只能通過輪詢的方式向服務器請求數據。

  ◇  網絡流量過大。就這個項目來說,網絡間傳遞的只是指令,但是每次傳遞都要加上一堆毫無用處的HTTP Head,再加上客戶端需要做輪詢,這個流量對于手機來說簡直恐怖,經簡單測試,按照0.03元/K的GPRS網絡費用計算,一局牌居然要消耗1元多的費用(每秒輪詢),實在不可接受。也許我們可以采用流量費包月的資費方式,不過這個話題與技術無關。

  以上問題導致我們選擇了Socket,這意味著我們將沒有一個web環境,很多東西都要靠自己去實現:線程管理、客戶狀態監控、對象池、控制臺……….網絡部分打算采用Java NIO來實現,這是一種新的網絡監聽方式,基于事件的異步通信,可以提高性能。每個客戶端連接之后,會有一個獨立的SocketChannel與它通信,這個SocketChannel會在用戶的整個生存周期中存在。用戶如果斷開連接,服務器會得到-1,并且會拋出Connection reset異常,通過捕獲這兩個特征,可以在用戶意外斷開連接后清理相關的資源。由于NIO是異步通信的,所以沒有復雜的線程管理。

二、             通信協議

  這個項目并沒有復雜的通信指令,命令數量很有限,但是還是有個關鍵問題需要關注:流量。為了盡量減小流量,我們使用字節代替字符串來保存系統指令,這樣可以使流量減少一半,比如使用一個字節來保存一張撲克牌,字節高位表示花色,字節低位表示數字,如果0代表黑桃,那么黑桃三就應該是0x03,這個需要靠位操作來實現:

int m=0;

    int n=3;

    byte card=(byte)(m)<<4)|((byte)n;       //m左移四位,然后與n左或操作

  游戲中需要傳遞用戶的積分,這是一個大整數,使用四個字節來保存比較保險,將整數轉換為四個字節的操作如下:

package org.bromon.games;
public static byte[] translateLong(long mark)

    {

        byte[] b = new byte[4];

        for (int i = 0; i < 4; i++)

        {

            b[i] = (byte) (mark >>> (24 - i * 8));

        }

        return b;

}

將四個字節轉回來的操作如下:

package org.bromon.games;

public static long translateByte(byte[] b)

    {

        int mask = 0xff;

        int temp = 0;

        int res = 0;

        for (int i = 0; i < 4; i++)

        {

            res <<= 8;

            temp = b[i] & mask;

            res |= temp;

        }

        return res;

}

三、             數據庫連接池

  由于沒有一個web環境,所以我們需要自己實現一個數據庫連接池,apache有一個項目叫做commons DBCP,這是一個基于apache自己的對象池(apache commons pool)實現的數據庫連接池,我們可以直接拿來使用,apache的軟件未必是最好的,但是極大可能比我們自己寫的要好。Commons DBCP需要三個.jar:commons-collections-3.1.jar、commons-dbcp-1.2.1.jar、commons-pool-1.2.jar這三個文件都可以在apache – Jakarta – commons項目下下載,加入到工程中即可。構造一個數據庫連接池的代碼如下:

package org.bromon.games;

import java.sql.*;

import com.gwnet.games.antiLord.util.*;

import org.apache.commons.dbcp.ConnectionFactory;

import org.apache.commons.dbcp.BasicDataSource;

import org.apache.commons.dbcp.DataSourceConnectionFactory;

private static BasicDataSource bds=new BasicDataSource();

private static ConnectionFactory fac=null;

//初始化連接池

bds.setDriverClassName(“org.postgresql.Driver”); //數據庫驅動程序

bds.setUrl(“jdbc:postgresql://localhost:5432/myDB”);  //數據庫url

bds.setUsername(“postgres”);                      //dba帳號

bds.setPassword(“XXXXXXXX”);              //密碼

bds.setInitialSize(100);                            //初始化連接數量

bds.setMaxIdle(10);                         //最大idle數

bds.setMaxWait(1000*60);                        //超時回收時間

fac=new DataSourceConnectionFactory(bds);       //得到連接工廠

Connection conn=fac.createConnection();         //從池中獲得連接

conn.close();                                   //釋放連接,回到池中

//銷毀連接池

bds.close();

bds=null;

fac=null;

請自行處理操作中的各種異常。

四、             撲克牌的生成

  游戲中需要為用戶生成隨機的撲克牌,首先我們需要初始化一副牌,放到一個Hashmap中,每張牌以一個字節表示,高為代表花色,的為代表數字,生成整副牌:

package org.bromon.games;

private static HashMap cards = new HashMap();

int tmp=0;

for (int i = 0; i <4; i++) {

for (int m = 0; m < 13; m++) {

tmp=((byte)(i)<<4)|((byte)m);   //使用位操作構造一張牌

cards.put(new Integer(i * 13 + m),new Byte((byte)tmp));

}

}

cards.put(new Integer(53), new Byte((byte)0x4d));   //大王

cards.put(new Integer(54), new Byte((byte)0x4e));   //小王

  如何隨機地得到其中的N張牌呢?我們的做法是生成一個0-55的隨機數,用這個隨機數作主鍵從Hashmap中獲得對象,取得之后,把該對象從隊列中刪除,以免重復取得。由于java中的隨機數是根據時間生成的,所以有可能導致用戶得到的牌不夠散,每個用戶都摸到一條龍豈不是笑話?所以在生成隨機數的時候我們加入了一個大素數來作運算:

long cardId=new Long((Math.round(Math.random() * 87) % 55)).intValue();通過修改這個大素數,可以控制某個用戶的牌比較好。

五、             線程

  實際上本系統并沒有復雜的線程管理,但是我想提供一個控制臺讓管理員可以管理游戲主線程,可以讓它停止、中段、恢復、重啟動,本來的設計是管理員通過與線程A打交道,通過A去管理主線程B,但是熟悉java線程的朋友都知道,線程互相管理基本上就是不實際的,舉個最簡單的例子,A如何銷毀B?也許你會說調用B的destroy()方法就好了,網上很多講解java線程的資料也確實是這么說的,但是他們都是鬼扯的,自己去看看java源代碼吧,Thread.destroy()方法的實際代碼如下:

package org.bromon.games;

public void destroy()

{

    throw new NoSuchMethodError();

}

  事實真相是,Thread.destroy()方法自始至終就沒有被實現過。所有寫文章,教別人用這個方法銷毀線程的人,都去撞墻吧,丟人丟大了。最好的辦法是A負責生成一個B并且啟動它,然后B自己管理生存周期,A和B通過使用可共享的方法來通信,這是sun推薦的做法。

六、             異步消息

  用戶玩牌的過程中,有很多東西需要記錄下來,比如記錄用戶的積分、等級變化,記錄玩牌日志供數據統計等,當用戶數量很多的時候,在數據庫中記錄這些信息會很耗費資源,用戶玩了一局之后會可能會等待很長時間。解決這個問題的方法是利用J2EE的消息bean來提供異步通信的機制,需要記錄數據的時候,系統會封裝一個值對象,發送給J2EE容器,這個操作是很快的,完成之后就返回,用戶可以繼續操作,不用關心消息何時被處理。J2EE的消息框架具備如下特征:

  ◇消息一定會被閱讀,而且只閱讀一次。JMS框架有自己的算法,把消息緩沖到硬盤,就算J2EE服務器死掉,消息也不會丟失。

  ◇系統采用點對點的Queue消息隊列,可以保證同等優先級的消息先進先出。

  在Jboss 4.0中,部署消息Bean和Queue隊列,都比weblogic 8.1來的容易,只需要在jboss.xml中聲明消息目的地,如果jboss發現該目的地不存在的話,會自動建立一個,實在很簡單。關于消息bean的開發與部署,我有專門的文章描述。

七、             啟動與退出

  為了讓系統具備讓人滿意的性能,應該盡量多的重用對象,減少創建新對象。比如上面提到的消息發送,我們的操作是提供一個靜態類,在系統啟動的時候就初始化,保持與JMS服務器的連接,系統發送消息的時候,不用再去查詢JNDI和生成QueueConnectionFactory,這樣可以提高系統響應速度。

  在數據庫連接池的問題上,我們也采用同樣的操作,啟動的時候初始化N個連接。但是如果在關閉進程的時候不做任何操作,會導致JMS拋出socket異常,雖然沒什么大的影響,但總顯得不專業,而且池中的連接不被釋放的話,也可能導致問題。最好能夠讓系統像jboss等控制臺程序一樣,ctrl+c之后能夠執行操作,釋放資源再退出。我們可以通過給進程/線程加上一個Hook來實現,windows程序員應該對這個非常熟悉。

Hook應該是一個線程方法,如下:

package org.bromon.games;

public class Hook extends Thread

{

    public void run()

    {

        //釋放數據庫連接,銷毀連接池

        //關閉與JMS的連接

    }

}

  在主線程中加入:Runtime.getRuntime().addShutdownHook(new Hook()) ;那么進程/線程會在退出的時候執行Hook的run方法,清理資源。
posted on 2007-04-28 15:39 Xiao.Zhu 閱讀(311) 評論(0)  編輯 收藏 引用

只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久gogo国模啪啪人体图| 亚洲一二三四区| 亚洲色在线视频| 免费在线国产精品| 久久人人97超碰国产公开结果| 欧美三日本三级少妇三2023| 日韩视频免费观看| 一区二区三区三区在线| 国产精品一区二区久久久久| 午夜精品一区二区三区在线| 午夜国产精品视频免费体验区| 国产欧美视频在线观看| 久久米奇亚洲| 欧美日韩激情小视频| 欧美一级视频| 另类图片综合电影| 亚洲国产成人精品视频| 久久国产精品亚洲77777| 欧美激情一区二区三区在线视频| 欧美在线观看一区| 欧美激情按摩在线| 国产日韩欧美亚洲一区| 国产一区二区丝袜高跟鞋图片| 国产日本精品| 国产精品99久久久久久久vr | 国产精品video| 亚洲综合成人在线| 91久久精品国产| 亚洲视频香蕉人妖| 亚洲精品视频一区二区三区| 久久精品视频va| 篠田优中文在线播放第一区| 欧美成人日韩| 老鸭窝91久久精品色噜噜导演| 国产精品久久久久久久第一福利| 亚洲精品视频免费| 99re6热在线精品视频播放速度| 国产日韩欧美精品一区| 欧美一级一区| 国产欧美日韩一区二区三区在线 | 久久精品国产在热久久| 99精品福利视频| 欧美激情一区二区| 亚洲免费精品| 亚洲综合首页| 国产私拍一区| 久久一区二区视频| 亚洲国产精品成人| 亚洲美女91| 国产精品久久久久永久免费观看| 91久久久久久| 亚洲主播在线观看| 国产网站欧美日韩免费精品在线观看| 亚洲一区在线直播| 欧美国产一区视频在线观看| 99视频精品| 国产欧美在线看| 欧美成人按摩| 亚洲欧美精品在线| 国产视频一区免费看| 久久最新视频| 午夜久久美女| 免费视频最近日韩| 国产精品久久久久9999| 久久xxxx精品视频| 一本久久a久久精品亚洲| 亚洲欧美日韩国产中文| 亚洲精品免费在线播放| 国产精品爽黄69| 欧美日韩卡一卡二| 久久国产视频网| 午夜电影亚洲| 亚洲一区二区三区四区在线观看 | 制服丝袜亚洲播放| 欧美成人精品h版在线观看| 亚洲性夜色噜噜噜7777| 1000部国产精品成人观看| 国产精品久久久久aaaa九色| 欧美精品国产精品| 久久亚洲欧美国产精品乐播| 欧美一区在线直播| 欧美伊人久久久久久久久影院| 在线中文字幕日韩| 日韩一级黄色av| 亚洲免费视频在线观看| 欧美中文字幕在线播放| 欧美影院在线| 久久综合精品一区| 欧美精品电影在线| 欧美三级欧美一级| 国产欧美日韩精品一区| 国产一区二区三区日韩| 亚洲国产精品一区二区三区| 久久综合九色综合网站| 久久女同互慰一区二区三区| 免费在线观看精品| 欧美午夜电影在线观看| 国产视频一区免费看| 国产一区二区三区黄视频| 99在线视频精品| 亚洲乱码国产乱码精品精可以看| 先锋影音一区二区三区| 欧美久久精品午夜青青大伊人| 国产精品国产精品| 亚洲黄一区二区三区| 久久久噜噜噜久久久| 亚洲视频在线观看| 欧美人与性动交α欧美精品济南到 | 国语自产偷拍精品视频偷| 中文网丁香综合网| 亚洲欧洲日韩女同| 免费成人高清视频| 亚洲高清在线| 欧美aa国产视频| 久久综合精品一区| 亚洲人成绝费网站色www| 中文成人激情娱乐网| 一本久久综合亚洲鲁鲁| 久久精品30| 在线日韩欧美视频| 欧美日韩亚洲在线| 国产精品美女久久久浪潮软件| 欧美性天天影院| 国产日韩一区在线| 国产精品萝li| 免费成人黄色av| 久久综合色播五月| 久久久www成人免费无遮挡大片 | 欧美精品一二三| 亚洲自拍偷拍视频| 一区二区三区中文在线观看| 一区二区三区 在线观看视| 国产精品久久久久久久久久直播 | 亚洲欧美高清| 国语对白精品一区二区| 欧美电影免费| 亚洲欧美日韩在线一区| 亚洲电影免费在线| 亚洲一区二区三区四区中文| 亚洲黄色尤物视频| 欧美成熟视频| 欧美在线视频日韩| 久久一区二区三区av| 亚洲国产成人av好男人在线观看| 欧美一区二区三区视频免费播放| 国产精品99久久久久久久女警| 红桃视频一区| 亚洲国产一二三| 日韩视频免费观看高清在线视频 | 欧美一区二区三区视频在线观看| 国产伦精品一区二区三| 欧美一区二区三区视频在线观看| 久久精品在线观看| 欧美亚洲自偷自偷| 欧美国产高潮xxxx1819| 欧美xx69| 国产日韩一区二区三区在线播放| 最新国产精品拍自在线播放| 国产日韩精品在线观看| 日韩一区二区免费高清| 欧美亚洲综合久久| 久久综合中文色婷婷| 国产精品男gay被猛男狂揉视频| 亚洲国产另类久久精品| 亚洲精品一区二区三区av| 极品日韩久久| 久久激情视频| 这里只有视频精品| 欧美午夜精品久久久| 91久久国产综合久久| 国产欧美精品一区aⅴ影院| 你懂的国产精品| 亚洲高清网站| 欧美日韩精品一二三区| 91久久精品国产| 久久成人综合网| 国产日韩在线一区| 久久精品国产综合精品| 亚洲电影观看| 亚洲天堂成人在线视频| 欧美视频网站| 亚洲综合激情| 蜜臀va亚洲va欧美va天堂| 亚洲人成网站影音先锋播放| 国产精品久久久亚洲一区| 亚洲精品一二| 午夜精品999| 狠狠色噜噜狠狠色综合久| 欧美黑人多人双交| 欧美国产在线电影| 一区二区精品| 欧美大片第1页| 久久成人18免费网站| 久久夜色精品国产噜噜av| 91久久国产综合久久蜜月精品 | 欧美午夜无遮挡| 99国产精品久久久久久久成人热| 欧美在线999| 在线综合视频| 国产精品99久久不卡二区|