[GAE] 用 Channel API 實作簡易聊天室
Blog 版:http://pt2club.blogspot.com/2011/09/channel-api.html
我不是故意要提 JavaScript 的
只是這玩意一定得搭配 JavaScript 啊...... Orz
========
Google App Engine 自 1.4.0 版推出 Channel API,
使 server 與 browser 之間可以不透過 pooling 的方式做到 server push。
不過 Google 官方教學文件摻雜了井字遊戲的元素,
反而無法專注於 Channel API 上。
這篇文章打算用最原始的聊天室,透過實做的過程來體驗一下 Java 版 Channel API。
因為是簡易聊天室,所以只打算提供一個共用的聊天室,
然後用兩個 JSP 檔來解決:room.jsp、server.jsp。
room.jsp 負責處理使用者輸入訊息、顯示對話;server.jsp
(應該寫成 servlet 比較好,因為是簡易聊天室......)
負責接收訊息、並廣播出去。
對應到 Channel API 的用詞,一個聊天室就是一個 channel,
同一個 channel 的成員(client 端)就會接收到其他成員所發出的訊息(message)。
所以,從 server 的角度,需要作這些事情:
1.開啟一個 channel
2.給加入這個 channel 的 client 專屬識別碼(token)
3.接收訊息的管道
4.發送訊息的功能
在 Channel API 當中只要決定 channel 的 名字就算做到第一點了,
因為是簡易聊天室,所以把名稱訂死為「PsMonkey」。
產生 token 的方法是:
//Java code
ChannelService channel = ChannelServiceFactory.getChannelService();
String token = channel.createChannel("PsMonkey");
因為是簡易聊天室,所以把 token 透過 JSP 產生、
並塞進 client 端的 JavaScript 碼。
接下來看 client 端的部份。首先建立連線的部份:
//JavaScript code
var channel = new goog.appengine.Channel("<%=token%>"); //token 傳入
var handler = {
'onopen' : onOpened, //建立連線、channel.open() 就會觸發
'onmessage' : onMessage, //有訊息傳入時
'onerror' : onError, //發生錯誤時
'onclose' : onClosed, //連線結束時
};
socket = channel.open(handler);
socket 就是實際處理通訊的部份。
這段的重點是透過 handler 設訂 socket 各種狀況會觸發的 method。
仔細想一下就會發現:「只有接收訊息的 method,那傳送訊息呢?」
Channel API 要解決的問題是 server push,
client 端傳送訊息的功能並不包含在其中,得透過 HTTP request 來作到。
所以送訊息的 method 會長的像這樣:
//JavaScript code
sendMessage = function(message) {
var xhr = new XMLHttpRequest();
xhr.open('POST', 'server.jsp?msg='+message, true);
xhr.send();
};
於是用 sendMessage() 來設定在 client 端連線時送出「____ 進入聊天室」、
離線時送出「____ 離開聊天室」:
//JavaScript code
onOpened = function() {
sendMessage("「"+name + "」進入聊天室......");
};
onClosed = function(){
sendMessage("「"+name + "」離開聊天室......");
}
有訊息進來的時候,就把訊息塞進某一個 element 的尾巴。
這邊要注意一點,參數 msg 不是單純的字串,而是一個物件,
data 這個 field 才是真正回傳的資料。
//JavaScript code
onMessage = function(msg) {
document.getElementById("output").innerHTML +=
msg.data +"<br />"";
}
接著來看一下負責處理 client 端 sendMessage() 的 server.jsp,直接貼程式碼:
//Java code
<%@ page language="java" contentType="text/html;
charset=UTF-8" pageEncoding="UTF-8"%>
<%@page import="com.google.appengine.api.channel.*"%>
<%
String message = request.getParameter("msg");
ChannelService channel = ChannelServiceFactory.getChannelService();
channel.sendMessage(
new ChannelMessage("PsMonkey", message)
);
%>
在從 request 當中取得 clinet 端傳上來的訊息後,
連同 channel 的名稱包成一個 ChannelMessage,
透過 ChannelService.sendMessage() 傳出去,
就會觸發 client 端的 socket.onMessage 了。
再透過一些簡單的 HTML 與 JavaScript 來讓 client 端
送出訊息時能呼叫到 sendMessage(),聊天室就完成了!
是不是很簡單呢? [扭扭]
最後補充 socket 的幾件事情:
onerror 會傳入一個參數,其中有兩個 field:
description:錯誤的描述
code:HTTP 錯誤代碼
目前只測出 idle 太久、server 切斷連線時會觸發
socket 還有一個 method:close(),呼叫成功會觸發 socket.onclose。
完整可以跑的範例放在... (我懶得貼網址了 XD)
--
錢鍾書: 說出來的話
http://www.psmonkey.org
比不上不說出來的話
Java 版 cookcomic 版
只影射著說不出來的話
and more......
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 114.25.0.25