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;
}
}