サーバーからの認識

株式会社シンメトリック新入社員の青木です。 オセロがオセロらしくなりましたがまだまだ満たすべき要件はあるということで続きを書いていきます。

今週の目標

今までの更新で簡単なチャットアプリにおけるWebsocketの通信機能部分をほぼそのまま使いまわすようにロジックの方向性を合わせていった結果、ブラウザ間でのオセロの通信対戦が一応できるようになりました。

しかし、参考元であるチャットアプリはサーバーに送られたテキストをそのまま接続中のブラウザにすべて返すだけで十分にチャットできますが、オセロのような対戦参加人数が2人と限定されているゲームでは、一手打つたびに接続中のブラウザすべてへ通信するのは意味はなく、それどころか同サーバー上で同タイミングにふたつ以上の対戦がなされている場合などに対戦相手の区別をつけられないのはゲームになりません。この部分をブラウザサイドで制御するというのも可能だとは思いますが、やはりサーバー側に無駄な労力がかかるため、これは現実を受け止めてサーバーできっちり判別させるべきだと考えました。

ですので、今週はサーバーサイドのJAVAを弄り、通信の指向性を持たせるということをします。

行ったアプローチ

サーバーサイドに手を入れていくといっても、そもそもJAVAのソースコードの読み方がわからず、それでも通信の機能だけ使えればよいとしたからこそ今までチャットアプリの一部を流用してきたのでした。とりあえずそのコードを改めて見てみます。


public class Oth {
private static ArrayList sessionList = new ArrayList();
    @OnOpen
    public void onOpen(Session session){
        sessionList.add(session);
    }
    @OnClose
    public void onClose(Session session){
        sessionList.remove(session);
    }
    @OnMessage
    public void onMessage(String str) throws IOException{
        for(Session session : sessionList){
            session.getBasicRemote().sendText(str);
        }
    }
}

 

これを読めないなりに読んでみると、接続時(onOpen)時と切断時(onClose)はその対象のセッションに区別されてArrayListに詰め込まれたり排除されたりされています。一方ブラウザからのメッセージが来た時(onMessage)には、文字列を受け取ってそれをそれぞれのセッションの区別をわざわざつけずにArrayListにあるセッションすべてに送っているように見えます。 onOpenとonCloseでは仮引数にSession型のものを定義しており、それが対象のセッションを認識しています。onMessageではString型のものを定義しており、それがブラウザから送られた文字列の認識となっているみたいなのがわかりました。

ですのでonMessageでも同じように仮引数にてSession型のもの定義すれば送信元のブラウザのセッションを識別できるのではないかと考え、仮因数にそのまま追加してみると、やはりその送信したブラウザを指定してサーバーからのデータの送信ができました。このようにセッションの識別がちゃんとできれば指向性を持たせるのは可能だとやっと私は認識しました。

しかしオセロ的には自分の一手の座標を自分ではなく相手に送信したいところです。ですがArrayListにセッションを格納していっても順序でしか判別がついてないみたいなので、これを使っていくのは難しいと考えました。

というところで、Mapというクラスを知りました。なんだかListのように詰め込めるようなものですが、Listと違って値だけではなくキーも同時に格納できて、キーがわかれば値を呼びだせるみたいです。 ですので、最初に名前等のキーにできるものを送らせ、その送信者のセッションを値としてMapに格納していけば、いざ対戦するときにはブラウザから座標などとともに相手の名前も送信すると、相手のセッションを識別して送ることができそうです。

作業結果

書いたとおりにできてしまいました。

sikokusei

左と右とで対戦していて上と下は異なる対戦をしていることが伝わると思います。

ここで調子に乗り、「接続中のセッション」ということ以外にもMapを多用したくなってしまい、サーバーサイドで発行した部屋の番号や現在対戦中であるプレイヤーを格納するためのMapを用意したのですが、そこで少し失敗しました。

Mapで格納されている要素が多くなってくるとWebsocketによる通信が途切れてしまうので、その格納された要素がいらなくなった場合は逐一消すということが必要になりました。 それでもはじめのうちは管理しきれていたのですが、欲張っていくとどのタイミングで消さなければならないかなどが把握しきれなくなってしまい、神経がすり減りました。

課題

今回はサーバーサイドについてのことを記述しましたが、来週はブラウザを触りたいです。実はオセロがオセロらしく動くとはいえ、javascriptのコードがたかだかオセロをするのに3500行ぐらいあるので、今まで見直すのが大変でありました。次の段階としてはデータベースに触る必要があるのですが、それに触る際にもjavascriptに手を加えることが必要になるはずなので、触る前にこの重さを改善することにします。

Page Top