HTML5中的WebSocket是个非常不错的技术,通过该技术可以像java中的socket一样可以在浏览器和服务器直接建立socket实现实时双向通讯.
目前支持webSocket客户端有Firefox 4、Chrome 4、Opera 10.70以及Safari 5等,android手机上的webkit等支持html5的都支持,在客户端除了直接使用websocket的api也可以使用jquery.socket.jsatmosphere.js socket.io等
Java服务器支持webSocket有tomcat 7.0.27, Netty 3.3.x,Jetty 7.x,GlassFish 3.1.2,比她们更高的版本当然也支持了
开始写第一个程序:
首先写一个websocket的helloworld,我这里客户端使用websocket原生api,服务器端使用tomcat 7
1.写客户端脚本,在页面中插入以下脚本:
思路:打开一个连接,为连接创建事件监听器(接收服务器的消息),发送消息到到服务器
<scripttype="text/javascript">
var socket = newWebSocket('ws://127.0.0.1:8080/websocket_test/helloWorld');
socket.onopen= function(event){
socket.send('I am the client and I\'m listening!');
socket.onmessage= function(event){
alert('来自服务器的消息:'+event.data);
};
socket.onclose= function(event){
//socket关闭
};
};
</script>
2.服务器端:接收到消息给客户端回复一个消息
<servlet>
<servlet-name>HelloWorldWebSocketServlet</servlet-name>
<servlet-class>com.auscend.servlet.HelloWorldWebSocketServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorldWebSocketServlet</servlet-name>
<url-pattern>/helloWorld</url-pattern>
</servlet-mapping>
packagecom.auscend.servlet;
importjava.io.IOException;
importjava.nio.ByteBuffer;
importjava.nio.CharBuffer;
importjavax.servlet.http.HttpServletRequest;
importorg.apache.catalina.websocket.MessageInbound;
importorg.apache.catalina.websocket.StreamInbound;
importorg.apache.catalina.websocket.WebSocketServlet;
importorg.apache.catalina.websocket.WsOutbound;
publicclassHelloWorldWebSocketServletextendsWebSocketServlet {
privatestaticfinallongserialVersionUID =1123456L;
@Override
protectedStreamInbound createWebSocketInbound(String subProtocol,
HttpServletRequestrequest) {
returnnewMessageInbound() {
@Override
protectedvoidonTextMessage(CharBuffer charBuffer)throwsIOException {
System.out.println("收到来自客户端的消息:"+charBuffer);
WsOutboundout=this.getWsOutbound();
CharBufferbuffer=CharBuffer.wrap("I'am server,I recevied yourmessage:"+charBuffer);
out.writeTextMessage(buffer);
out.flush();
}
@Override
protectedvoidonBinaryMessage(ByteBuffer byteBuffer)throwsIOException {}
};
}
}
服务器端支持websocket由于要使用tomcat7中的api,这里要导入catalina.jar和tomcat-coyote.jar这两个包,不过不要把这个两个包放在WEB-INF下,因为我们不需要把这两个包部署到tomcat中,部署过去会出错(参考http://blog.csdn.net/meiwen1111/article/details/7792923)
就上面的代码,简单补充说明:
客户端:
Websocket的api:http://www.w3.org/TR/websockets/ 中文:http://www.w3.org/html/ig/zh/wiki/WebSocket
Api中描述了WebSocket的接口
[Constructor(DOMString url, optional (DOMString or DOMString[]) protocols)]
/**
new WebSocket(url,protocols)第一个参数是url,第二个参数是一个协议或者协议数组,可以不写,上面的例子中使用ws://127.0.0.1:8080/websocket_test/helloWorld 做为url,其中ws和http一样,表示什么协议。怎么连接和封装数据包。
**/
interface WebSocket : EventTarget {
readonly attribute DOMString url; //当前对象连接的url
// ready state
const unsigned short CONNECTING = 0; // 还没建立连接
const unsigned short OPEN = 1; // 建立了连接
const unsigned short CLOSING = 2; // 正在关闭连接 一般是 close()方法已经被调用
const unsigned short CLOSED = 3; //连接已经关闭
readonly attribute unsigned short readyState; //当前对象的状态,上面的四个值
readonly attribute unsigned long bufferedAmount; //排队等待发送的字节数
// networking
attribute EventHandler onopen; //连接建立时做什么
attribute EventHandler onerror; //发生错误时做什么
attribute EventHandler onclose; //关闭连接做什么
readonly attribute DOMString extensions; //原来扩展
readonly attribute DOMString protocol; //协议
void close([Clamp] optional unsigned short code, optional DOMString reason);
/**
调用close方法时,可以不写参数。如果提供第一个参数,第一个参数不应该是1000,而应该是3000 到 4999的数字,这样会抛InvalidAccessError 异常。如果提供第二个参数,第二个参数应该表示出异常的原因,也就是对第一个参数的补充。
**/
// messaging
attribute EventHandler onmessage; //收到消息做什么
attribute DOMString binaryType; //设置event.data的类型,你设置成什么websocket就会给你封装成什么类型,常用的几种: arrayBuffer 和 blob
//通过send发送不同类型的数据
void send(DOMString data);
void send(Blob data);
void send(ArrayBuffer data);
void send(ArrayBufferView data);
};
这样我们的客户端如何编程就清楚了。
使用tomcat7对websocket进行服务器端的编程:文档:http://tomcat.apache.org/tomcat-7.0-doc/api/index.html?org/apache/catalina/websocket/package-summary.html
用WebSocketServlet可以处理客户端websocket的链接,这个类也是HttpServlet的子类,所以他本身就是一个servlet,自己写类继承WebSocketServlet。
如果是处理http请求,那么会调用doGet或 doPost也一样,这里对websocket主要是
protected abstract StreamInbound createWebSocketInbound(String subProtocol,HttpServletRequest request)方法
用来和客户端建立连接,参数(协议和用来建立连接的请求)基本不使用。这里要返回一个StreamInbound对象用来处理与客户端的连接,相当于javanet包中的Socket对象
我们在重写这个方法时,要返回一个StreamInbound的对象,自己new一个StreamInbound的子类的对象,我们常用StreamInbound的子类MessageInbound
对MessageInbound请参看api,基于这个类的对象,可以发送数据到客户端,也可以接受客户端的各种类型的数据
在网上有关于聊天室的例子,这里说说思路:
打开网页后,网页中执行脚本和服务器建立websocket连接,服务器就把和客户端对应的StreamInbound对象保存到一个集合中,当客户端有消息发过来时,服务器把这个消息通过StreamInbound的集合发给每个其他客户端,网页中收到消息把消息显示在页面上。和java.net.Socket的编程思路一致,如果添加功能,参照java.net.Socket的编程思路。