MASATOの開発日記


前の開発日記 次の開発日記 一覧

2002/10/27

最近Javaに染まりぎみ。J2SE1.4 + Tomcat + AxisでWebサービスのサーバサイドを構築して、 C#でクライアントを作成して遊んでおります。

ネットワークゲームにおいて送受信するデータの内容(1)

将来ネットワーク対応したいけれど、とりあえず最初はスタンドアロンで動くものを作ろうという考えのもと、 あるゲームを作っています。
サーバ及び各クライアントで、グローバルデータのような感じで、 ゲームの画面表示等に必要なデータはすべて共用しようという設計でした。 といってもネットワークの線にデータを置く、ってことはできませんので、 サーバやクライアントで同じデータを保持し、データの一部を変更したら 変更情報を通知すれば良いと考えておりました。
一応、変更情報の送信側となるのはサーバだけであり、クライアントがデータを変更したいと 思った場合はサーバに伺いを立てるようにすればよいと考えておりました。
例えば、サーバで何か処理を行った後、「AのMPが90になり、BのHPが70になり、Bが毒状態になる」というような、 その結果どうなったかという情報を送信するわけです。

しかし、開発が進むにつれて、この方法ではネットワーク対戦が困難であるような気がしてきました。 その理由は、データの規模がどんどん大きくなってきたことでした。
例えば、「Aの魔法により、BのHPに30のダメージと毒を与えた」 という、何が起こったかを表す情報を送信する必要が発生しました。 なぜなら、クライアントの画面に、「ダメージ30」「POISON」と表示させる必要があったからです。
このようにデータの規模が大きくなると、どれが更新されたかを判断し、制御するための実装が困難になっていきました。
複雑なロジックになったため困難だったのではなく、単調な実装をひたすら繰り返さなければならないので 面倒だと思ったのです。

そこで、その結果どうなったかという情報を送る考えをすっぱり捨て、次のような方法を とりました。というところで以下次号。

(2002/10/28) 推敲。

ファイルを用いた排他ロック方法

環境Java2 1.4 Standard Edition

今回から話題はJavaに移ります。 複数のプロセス間で危険領域を扱うための方法です。 ファイルロックとも呼ばれ、CGIでは一般的に使われています。
例えば複数のプロセスにおいて同じファイルを操作したいとき、 あるプロセスAがファイル操作中に、他のプロセスBがファイル操作を行ったら ファイルの内容が壊れてしまい、困ったことになります。 今回説明する方法では、こんな場合に、プロセスBのファイル操作を 待たせておくことができます。

なお、この方法はバージョン1.4以降でないと使えません。また、複数のプロセスではなく、 1つのプロセス内の複数のスレッドならば、synchronizedで制御できますので、 排他ロックのためにわざわざファイルを使わなくとも良いでしょう。

以下に排他ロックのサンプルコードを示します。

import java.io.*;
import java.nio.channels.*;

// 中略

    try {
      File file = new File("ファイル名");
      FileChannel channel = new RandomAccessFile(file, "rw").getChannel();
      FileLock lock = channel.lock();
      // 危険領域となる処理
      lock.release();
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

// 後略

RandomAccessFileを使った理由は、FileLockクラスのlockメソッドの解説に 「このチャネルは書き込み (場合によっては読み込みも) 可能でなければならない」 と曖昧な記述があるので、どちらに転んでも不都合が無い読み書き可能なチャネルにしたかったためです。

FileChannelは共有ロック機能もありますので、これについても後ほど解説したいと思います。

(2003/07/24) 例外処理を細かく記述した。

前の開発日記 次の開発日記 一覧