libro
www.tuyano.com
Google App Engine for Java(GAE/J)プログラミング入門

Channel APIによるクライアント=サーバー双方向通信 (4/5)

作成:2012-07-08 10:01
更新:2012-07-08 10:16

■チャンネル利用の実際

では、ここまで説明した内容を簡単なサンプルとしてまとめたものを挙げておきましょう。下のリスト欄に掲載をしておきます。ここでは、サーブレットは"/mygae"というパスに公開するようにしてありますので、web.xmlの設定を忘れずに行なって下さい。

HTMLにアクセスすると、そのままMyGaeAppServletにAjaxを使ってGETアクセスを開始し、チャンネルを作成してそのトークンをテキストフィールドに表示します。そのまま横のボタンをクリックすると、チャンネルがオープンされ通信が開始されます。

下の入力欄にテキストを書いてボタンを押すと、そのメッセージがサーバーに送信され、チャンネルを経由して返されたメッセージがページの下部に表示されていきます。ごくごく単純にメッセージをやりとりしているだけのサンプルですが、チャンネルの働きをシンプルに理解するには十分でしょう。

ここでは、「チャンネルキーを指定してサーバーに送信」「指定のチャンネルを使ってクライアントに返信」といった形でやり取りをしています。アクセスしているクライアントとサーバーが、常に1対1でやり取りしていることがわかります。

今回、「アクセス時にチャンネル作成」「ボタンを押して通信開始」というように、チャンネル作成と通信の開始を分けてありますが、これは単に両者を切り分けてわかりやすくしたというだけです。実際にはこれらは一連の処理としてまとめて行うようにすると便利でしょう。またトークンも隠蔽して表示されないようにしたほうがよいかも知れませんね。

(ちなみに、あくまでサンプルですので、メッセージのエンコード処理などはしていません。なので日本語は文字化けします。そのへんはそれぞれで適当に作り替えてください)

※プログラムリストが表示されない場合

AddBlockなどの広告ブロックツールがONになっていると、プログラムリスト等が表示されない場合があります。これらのツールをOFFにしてみてください。

●プログラム・リスト●

※サーブレット(mygae)のソースコード

package com.tuyano.libro;

import com.google.appengine.api.channel.ChannelMessage;
import com.google.appengine.api.channel.ChannelService;
import com.google.appengine.api.channel.ChannelServiceFactory;

import java.io.IOException;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@SuppressWarnings("serial")
public class MyGaeAppServlet extends HttpServlet {
    
    public void doGet(HttpServletRequest request, 
      	  HttpServletResponse response)
            throws IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/plain;charset=utf-8");
        ChannelService channelService = ChannelServiceFactory
                .getChannelService();

        String channelKey = request.getParameter("channelKey");
        String token = channelService.createChannel(channelKey);
        response.getWriter().println(token);
        channelService.sendMessage(new ChannelMessage(channelKey,
                "Hello World!"));
    }

    public void doPost(HttpServletRequest request, 
            HttpServletResponse response)
            throws IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/plain;charset=utf-8");
        ChannelService channelService = ChannelServiceFactory
                .getChannelService();
        String channelKey = request.getParameter("channelKey");
        String message = request.getParameter("message");

        if (message == null || message == "") {
            channelService.sendMessage(new ChannelMessage(channelKey,
                    "connected now!"));
        } else {
            channelService.sendMessage(new ChannelMessage(channelKey,
                    "you send '" + message + "'!"));
        }
        return;
    }

}


※HTMLファイルのソースコード

<html>
  <head>
    <style type="text/css">
      h1 {
        font-size:14pt;
        background-color:FFDDFF;
      }
    </style>
  </head>
  <body>
    <script src='/_ah/channel/jsapi'></script>
    <script>
      var channel;
      var channelKey = "KEY" + new Date().getTime();
      var socket;
      var connected;
      
      function createChannel(path){
        var xhr = new XMLHttpRequest();
        xhr.open('GET', path + '?channelKey=' + channelKey, true);
        xhr.onreadystatechange = function(){
          if (xhr.readyState == 4 && xhr.status == 200){
            createChannelCallback(xhr);
          }
        };
        xhr.send();
      };
      
      function createChannelCallback(request){
        var token = document.querySelector('#token');
        token.value = request.responseText;
      };
      
      function sendMessage(path, msg) {
        var xhr = new XMLHttpRequest();
        xhr.open('POST', path + '?channelKey=' + channelKey +
                 '&message=' + msg, true);
        xhr.send();
      };
      
      var onOpened = function() {
        connected = true;
        alert("opened!");
      };
      var onMessage= function(param) {
        var ul = document.querySelector('#list');
        ul.innerHTML = '<li>' + param.data + '</li>' + ul.innerHTML
      };
      var onError = function(e){
        alert("error:[" + e.code + "]" + e.description);
      };
      var onClose = function() {
        connected = false;
        alert("close");
      };
      
      function openChannel() {
        var token = document.querySelector('#token').value;
        channel = new goog.appengine.Channel(token);
        socket = channel.open();
        socket.onopen = onOpened;
        socket.onmessage = onMessage;
        socket.onerror = onError;
        socket.onclose = onClose;
      }
      
      function initialize() {
        createChannel('mygae');
        document.body.onunload = function(){
          try {
            socket.close();
          } catch(e){}
        }
      }
      
      function doAction(){
        var msg = document.querySelector('#msg').value;
        sendMessage("mygae", msg);
      } 
      
      setTimeout(initialize, 100);
    </script>
    <h1>
      sample
    </h1>
    TOKEN:<input type="text" id="token">
    <button onclick="openChannel();">click</button>
    <hr>
    MESSAGE:<input type="text" id="msg">
    <button onclick="doAction();">click</button>
    <hr>
    <ul id="list"></ul>
  </body>
</html>

※関連コンテンツ

「Google App Engine for Java(GAE/J)プログラミング入門」に戻る