2010/12/19 22時頃追記
『通信を手動で終了した場合に、謎のiframeが残ってしまい再接続ができない』
というGAE側の?バグが確認されました。
このページで公開されているソースは、このバグ対策用コードも含みます。
詳細はこのページをご覧になってください。
2010-12-19 - 風柳メモ「Google App Engine/PythonのChannel APIを使ってみた」
Google App Engine Channel APIのサーバ側のサンプルコードです。
クライアント側のHTML、JavaScriptのコードはこのページです。
『Channel APIを使うプログラムのクライアント側のコード』
上記のURLのソースコードで作ったChannel APIアプリケーションはこちらです。
ソースにコメントをたくさん書いておいたので、JavaScriptについてあまり詳しくなくても読めるはず?です。
『実際に動作しているChannel API アプリケーションページ』
元のページはこちらです。
『Google App Engine Channel APIの使い方』
サーバとクライアントのサンプルコードはそのままデプロイすればGoogle App Engine上で動きます。
もし分からないことがあったら、@ts_3156に何でもリプライして聞いてください。
import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.google.appengine.api.channel.ChannelMessage; import com.google.appengine.api.channel.ChannelService; import com.google.appengine.api.channel.ChannelServiceFactory; @SuppressWarnings("serial") public class ChannelAPITestServlet extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { // ゲームに割り当てられるIdとか、ログインしたユーザのIdとか自分で決めましょう // ここではとりあえず時間を表す文字列にしてます String userId = Long.toString(System.currentTimeMillis()); String htmlSource = "http://channel3156.appspot.com/channel_api_test.htmlのHTMLをそのまま代入"; StringBuilder strBuilder = new StringBuilder(); BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("channel_api_test.html"), "utf-8")); String line = null; while((line = br.readLine()) != null) strBuilder.append(line + "\n"); htmlSource = strBuilder.toString(); htmlSource = htmlSource.replaceAll("--token--", getToken(userId)); htmlSource = htmlSource.replaceAll("--userId--", userId); resp.setContentType("text/html; charset=utf-8"); resp.getWriter().write(htmlSource); } public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { String getToken = req.getParameter("getToken"); // Token再取得要求 if(getToken != null && getToken.equals("true")){ String userId = Long.toString(System.currentTimeMillis()); String token = getToken(userId); String response = "{\"userId\": \"" + userId + "\", \"token\": \"" + token + "\"}"; resp.setContentType("text/html; charset=utf-8"); resp.getWriter().write(response); return; } String userId = req.getParameter("userId"); String message = req.getParameter("message"); String sendTime = req.getParameter("time"); long curTime = System.currentTimeMillis(); String sendTimeStr = "" + (curTime - Long.parseLong(sendTime)); // 受け取ったデータをそのまま返します String response = "{\"text\": \"" + message + "を受け取ったよ! 送信: " + sendTimeStr + "ミリ秒" + "\", \"time\": \"" + curTime + "\"}"; sendUpdateToUser(userId, response); } private void sendUpdateToUser(String userId, String message) { ChannelService channelService = ChannelServiceFactory.getChannelService(); channelService.sendMessage(new ChannelMessage(userId, message)); } private String getToken(String userId){ ChannelService channelService = ChannelServiceFactory.getChannelService(); // ゲームのパラメータとかユーザIdを元にして一意なIdを作りましょう // ここでは簡易化のために、userIdをそのまま使っています String token = channelService.createChannel(userId); return token; } }