人工知能に関する断創録

このブログでは人工知能のさまざまな分野について調査したことをまとめています(更新停止: 2019年12月31日)

サーバー上のファイルにスコアを保存する

CGIへスコア情報を送信する(2005/8/7)の続きです。

前回はCGIへスコアを送りましたが CGI側でそのスコアを保存していませんでした(ハイスコア出した人ごめんなさいってなってしまいます)。今回は、CGI側でスコアを保存する処理を追加します。CGIはサーバー上で動いているのでスコア情報はサーバー上のファイルに保存されます

前回と同じく、必要最小限の構成にするためコンソールアプリケーションを作りました。実行するにはファイルをダウンロードしてrun.batをダブルクリックしてください。ただ私の使っているサーバーにスコア情報が送信されてしまうためスコアが本当に登録されたかまだ確認する方法がありません・・・確かめたい場合はご自分でサーバーを用意する必要があります

register_score.zip

CGIでスコアを保存する

前回のプログラムから主に書き換えるのは、perlで書いたCGIプログラムだけです。前回はスコア情報を受け取ってそのまま破棄してましたが、スコアを保存するように書き換えます。短いので全部掲載します。

#!/usr/bin/perl
use POSIX 'strftime';
use Fcntl ':flock';

# 送信されたデータを受け取る
if ($ENV{'REQUEST_METHOD'} eq "POST") {
    read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
}

# データを分割する
@pairs = split(/&/, $buffer);
# 各データをさらに分割して%paramハッシュに入れる
foreach $pair (@pairs) {
    ($key, $value) = split(/=/, $pair);
    # valueが日本語の場合コード化されているので変換する
    $value =~ s/%([a-fA-F0-9][a-fA-F-0-9])/pack("C", hex($1))/eg;
    $param{$key} = $value;
}

# スコアをサーバー上のファイルに書き込む
unless (open(OUT, ">>score.txt")) {  # score.txtを追加書き込みモードで開く
    print "Sorry, I couldn't create score.txt\n";
} else {
    # 現在時刻を取得
    $now = strftime("%Y/%m/%d %H:%M", localtime);
    flock(OUT, LOCK_EX);  # ファイルをロック
    # 現在時刻、名前、スコアを書き込む
    print OUT "$now&$param{name}&$param{score}\n";
    flock(OUT, LOCK_UN);  # ロックを解除
}
close(OUT);  # ファイルを閉じる

# 出力されるHTML
print <<END;
Content-type: text/html

<html>
<head><title>あなたの得点は登録されました</title></head>
<body>
<h1>あなたの得点は登録されました</h1>
<p>$param{name}さんは$param{score}点です。</p>
</body>
</html>
END

重要なところは、スコアをサーバー上のファイルに書き込む部分です。score.txtというファイルにスコア情報を書き込みます。スコア情報は、

 2005/08/15 10:46&もり&1500
 2005/08/15 10:46&もり&1500
 2005/08/15 10:47&ななし&50
 2005/08/15 10:47&ななし&9999

こんな風に書き込むことにしました。3つのデータを&で区切って保存します。1つ目はスコアを登録した時間、2つ目はプレイヤーの名前、3 つ目はスコアです。1行が1回のプレイのデータです。perlでファイルに書き込む処理はJavaに比べて非常に簡単です。

  1. open(OUT, ">>score.txt")でファイルを開く、OUTはファイル識別子
  2. print OUT "書き込みたいデータ";

です。ファイルに書き込むときにはflock()をしておくと安全です。多数のユーザーが同時にサーバー上のファイルを書き直そうとするとファイルを壊してしまうことがあるからです。ロックをしておくと同時書き込みができなくなるのでファイルが壊れなくなります。Java側はほとんど書き直す必要はありません。接続するCGI名をsend_score.cgiからregister_score.cgiに書き直しただけです。ご自分でサーバーを持っている方はregister_score.cgiをアップ(パーミッション755)してアクセスしてみましょう。サーバー側にscore.txtというファイルが出来てスコアが書き込まれているはずです。