オンラインの将棋類のネットゲームjavaサービス端は実現します

23465 ワード

本文はネットから来て、長い間見て、所蔵されてからずっと見ていないで、今日見た後にサイトに所蔵して、原文の住所:http://kakaluyi.iteye.com/blog/1489592. 一、ネットワーク
ネットゲームは、まず直面する問題はもちろん、どのようにネット通信を行うかです.まず考えたのはHTTPプロトコルで、すべてのJ 2 ME携帯電話がこれをサポートしているので、私たちはもちろんできるだけユーザーと互換性を持ちたいと思っています.また、HTTPプロトコルのパッケージ化の程度は非常に高く、スレッド、同期、状態管理、接続プールを考慮する必要はありませんが、HTTPプロトコルには2つの不快な点があります.
◇協議が無状態で、この問題は何度も困ったことがある.私が考えた解決策はHTTPプロトコルを改造し、データ転送が完了した後にsocketを閉じないことですが、このような作業量は非常に大きく、プロジェクトサイクルでは基本的にMissionimpossibleであり、考慮しません.お客様は、ポーリングによってサーバにデータを要求するしかありません.
◇ネットの流れが大きすぎる.このプロジェクトについて言えば、ネット間で伝達されるのは命令だけだが、伝達するたびに役に立たないHTTPHeadが山積みになり、クライアントがポーリングする必要がある.この流量は携帯電話にとって恐怖で、簡単なテストを経て、0.03元/KのGPRSネットワーク費用で計算すると、1局のカードが1元以上の費用(毎秒ポーリング)を消費するなんて、本当に受け入れられない.流量費で月額を包む料金方式を採用できるかもしれませんが、この話題は技術とは関係ありません.
以上の問題でSocketを選択しました.これは、スレッド管理、顧客ステータスモニタリング、オブジェクトプール、コンソールなど、Web環境がないことを意味します.
ネットワーク部分はJavaNIOで実現する予定で、イベントベースの非同期通信で性能を向上させる新しいネットワーク傍受方式です.各クライアントが接続されると、ユーザーのライフサイクル全体にわたって存在する独立したSocketChannelが通信します.ユーザが接続を切断すると、サーバは-1を取得し、Connectionresetの異常を放出します.この2つの特徴をキャプチャすることで、ユーザが予期せぬ接続を切断した後に関連するリソースをクリーンアップできます.NIOは非同期通信であるため,複雑なスレッド管理はない.
二、通信プロトコルというプロジェクトには複雑な通信命令はなく、コマンドの数は限られているが、トラフィックに注目しなければならない重要な問題がある.トラフィックを最小限に抑えるために、文字列の代わりにバイトを使用してシステム命令を保存します.これにより、トラフィックを半分に減らすことができます.例えば、1バイトを使用してトランプを保存し、バイトの高位は花色を表し、バイトの低位は数字を表し、0が黒桃を表す場合、黒桃3は0であるべきです.×03、これはビット操作で実現する必要があります.
1
2
3
int  m=0;
    int  n=3;
    byte  card=(byte )(m)<<4)|((byte )n; //m    ,   n    

ゲームではユーザーのポイントを渡す必要があります.これは大きな整数で、4バイトを使用して比較保険を保存し、整数を4バイトに変換する操作は以下の通りです.
1
2
3
4
5
6
7
8
9
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;
}

4バイトを戻す操作は次のとおりです.
1
2
3
4
5
6
7
8
9
10
11
12
13
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にはcommonsDBPPというプロジェクトがあります.これはapache自身のオブジェクトプール(apache commonspool)に基づいて実現されたデータベース接続プールです.私たちは直接使用することができます.apacheのソフトウェアは必ずしも最高ではありません.しかし、私たち自身が書いたよりも良い可能性が高い.
Commons DBPPには3つの.jarが必要です.
commons-collections-3.1.jar、commons-dbcp-1.2.1.jar、commons-pool-1.2.jar
この3つのファイルはapacheにありますか?Jakarta ? commonsプロジェクトの下でダウンロードして、工事に参加すればいいです.
データベース接続プールを構築するコードは次のとおりです.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import java.sql.Connection;
import java.sql.SQLException;
 import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.ConnectionFactory;
import org.apache.commons.dbcp.DataSourceConnectionFactory;
 public class SqlTools {
 private static BasicDataSource bds = new BasicDataSource();
    private static ConnectionFactory fac = null;
 public static void main(String[] args) throws SQLException {
        //       
        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に置く必要があります.各トランプは1バイトで表され、高さは花色を表し、数字を表し、トランプ全体を生成します.
1
2
3
4
5
6
7
8
9
10
11
12
13
private static HashMap<Integer, Byte> cards = new HashMap<Integer, Byte>();
 public static void pai() {
        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の乱数は時間によって生成されるため、ユーザーが得たカードが散らばっていない可能性があり、ユーザー一人一人が竜を触っているのは冗談ではないでしょうか.ランダム数を生成するときに大きな素数を加えて演算します.
1
long  cardId=new  Long ((Math.round(Math .random() * 87) % 55)).intvalue();

この大素数を修正することで,あるユーザのカードを制御できるとよい.
五、スレッド
実际には本システムは复雑なスレッド管理はありませんが、管理者がゲームのメインスレッドを管理できるコンソールを提供したいと思っています.停止、中段、回复、再起动させることができます.本来の设计は管理者がスレッドAと付き合うことで、Aを通じてメインスレッドBを管理することですが、javaスレッドに详しい友达は知っています.スレッドの相互管理は基本的に現実的ではありません.最も簡単な例を挙げると、AはどのようにBを破棄しますか.Bのdestroy()メソッドを呼び出せばいいと言うかもしれませんが、ネット上でjavaスレッドを説明する多くの資料も確かにそう言っていますが、彼らはみなでたらめなので、自分でjavaソースコードを見てみましょう.Thread.destroy()メソッドの実際のコードは以下の通りです.
1
2
3
4
public  void  destroy() 
{
    throw  new  NoSuchMethodError ();
}

事実の真相は、Thread.destroy()の方法は最初から最後まで実現されていないことだ.文章を書いたり、この方法でスレッドを破棄したりする人は、壁にぶつかったりして、恥ずかしくてたまらない.
最良の方法は、AがBを生成して起動し、Bが自分で生存サイクルを管理し、AとBが共有可能な方法で通信することであり、sunが推奨する方法である.
六、非同期メッセージ
ユーザーがトランプをする過程で、ユーザーのポイント、等級の変化を記録したり、トランプのログを記録してデータ統計をしたりするなど、多くのものを記録する必要があります.ユーザーの数が多い場合、データベースにこれらの情報を記録するのにリソースがかかり、ユーザーが1セット遊んだ後、長い間待つ可能性があります.この問題を解決する方法はJ 2 EEのメッセージbeanを利用して非同期通信のメカニズムを提供することであり、データを記録する必要がある場合、システムは値オブジェクトをカプセル化し、J 2 EEコンテナに送信する.この操作はすぐで、完了したら戻って、ユーザーは操作を継続することができ、メッセージがいつ処理されるか気にしない.
J 2 EEのメッセージフレームワークは以下の特徴を備えている.
◇ニュースは必ず読まれ、しかも一度しか読まない.JMSフレームワークには独自のアルゴリズムがあり、メッセージをハードディスクにバッファリングし、J 2 EEサーバが死んでもメッセージは失われない.
◇システムはポイント対ポイントのQueueメッセージキューを採用しており、同等の優先度のメッセージが先に出ることを保証できる.
Jboss 4.0では、配置メッセージBeanとQueueキューは、weblogic 8.1よりも容易であり、jboss.xmlでメッセージ宛先を宣言するだけで、jbossがその宛先が存在しないことを発見した場合、自動的に1つ作成されるので、本当に簡単です.
七、起動と退出
システムが満足できるパフォーマンスを得るためには、オブジェクトをできるだけ多く再利用し、新しいオブジェクトの作成を減らす必要があります.例えば、上記のメッセージ送信では、システムの起動時に初期化し、JMSサーバとの接続を維持する静的クラスを提供し、システムがメッセージを送信する際に、JNDIをクエリーしたりQueConnectionFactoryを生成したりすることなく、システム応答速度を向上させることができます.
データベース接続プールの問題でも同様の操作を行い、起動時にN個の接続を初期化します.しかし、プロセスを閉じるときに何もしないと、JMSがsocket異常を投げ出すことになり、大きな影響はありませんが、プロフェッショナルではなく、プール内の接続が解放されないと問題になる可能性があります.システムをjbossなどのコンソールプログラムのようにctrl+c後に操作を実行し、リソースを解放して終了させることが望ましい.プロセス/スレッドにHookを追加することで実現できます.windowsプログラマーはこれに詳しいはずです.
Hookは次のようなスレッド方法であるべきです.
1
2
3
4
5
6
7
8
9
10
11
12
public  class  Hook extends  Thread
{
    public  void  run()
    {
        //       ,     
        //   JMS   
    }
}
 //       :
 Runtime .getRuntime().addShutdownHook(new  Hook()) ;

プロセス/スレッドは終了時にHookのrunメソッドを実行し、リソースをクリーンアップします.