作者PsMonkey (痞子军团团长)
看板java
标题[GAE] 用 Channel API 实作简易聊天室
时间Wed Sep 28 17:48:01 2011
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