WebSocket是HTML5一种新的协议。它实现了浏览器与服务器全双工通信(full-duplex),能更好的节省服务器资源和带宽并达到实时通讯,它建立在TCP之上,同HTTP一样通过TCP来传输数据,但是它和HTTP最大不同是:
WebSocket是一种双向通信协议,在建立连接后,WebSocket服务器和Browser/Client Agent都能主动的向对方发送或接收数据,就像Socket一样;
WebSocket需要类似TCP的客户端和服务器端通过握手连接,连接成功后才能相互通信。
在实现websocket连线过程中,需要通过浏览器发出websocket连线请求,然后服务器发出回应,这个过程通常称为“握手” (handshaking)。
本范例在apache-tomcat-7.0.69环境下测试通过,工程主要用到以下jar包:websocket-api.jar(Tomcat自带)、tomcat-juli-7.0.27.jar等。
Java类源码:
@ServerEndpoint("/websocket")
public class MyWebsocket {
private Timer timer;
private static AtomicLong socketCount = new AtomicLong();
private Session session;
//客户端和服务端建立链接的Websocket集合
private static CopyOnWriteArraySet<MyWebsocket> webSocketSet = new CopyOnWriteArraySet<MyWebsocket>();
/**
* 建立链接
*/
@OnOpen
public void onOpen(Session session){
this.session = session;
webSocketSet.add(this);
//启动一个单独的线程,每隔一秒钟推送当前时间到web客户端
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//batch(sdf.format(new Date()));
}
}, 0, 1000L);
System.out.println("session count is " + socketCount.incrementAndGet());
}
/**
* 关闭链接
*/
@OnClose
public void opClose(){
webSocketSet.remove(this);
if(timer != null){
timer.cancel();
timer = null;
}
System.out.println("session count is " + socketCount.decrementAndGet());
}
/**
* 服务端接收客户端发来的消息
* @param message
* @param session
*/
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("来自客户端的消息:" + message);
batch(message);
}
/**
* 往所有web客户端发送消息
* @param message
*/
private void batch(String message){
for(MyWebsocket item: webSocketSet){
try {
item.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
continue;
}
}
}
/**
* 发送消息到web客户端
* @param message
* @throws IOException
*/
public void sendMessage(String message) throws IOException{
this.session.getBasicRemote().sendText(message);
//this.session.getAsyncRemote().sendText(message);
}
/**
* 异常处理
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error){
System.out.println("发生错误");
error.printStackTrace();
}
}
JSP页面代码:
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Web Socket</title>
</head>
<body>
<input id="text" type="text" />
<button οnclick="send()">Send</button>
<button οnclick="closeWebSocket()">Close</button>
<div id="message">
</div>
<script type="text/javascript">
var websocket = null;
if('WebSocket' in window){
websocket = new WebSocket("ws://localhost:8080/ws/websocket");
}else{
alert('Not support websocket');
}
//连接出现错误,触发该方法
websocket.onerror = function(){
setMessageInnerHTML("error");
};
//成功建立连接,触发该方法
websocket.onopen = function(event){
setMessageInnerHTML("连接已建立,可以开始群聊啦!");
}
//客户端收到消息,触发该方法
websocket.onmessage = function(event){
setMessageInnerHTML(event.data);
}
//连接关闭,触发该方法
websocket.onclose = function(){
setMessageInnerHTML("连接已关闭!");
}
//窗口关闭时,关闭websocket连接
window.onbeforeunload = function(){
websocket.close();
websocket = null;
}
//将消息显示在网页上
var i = 0;
function setMessageInnerHTML(innerHTML){
document.getElementById('message').innerHTML = innerHTML + '<br/>' + document.getElementById('message').innerHTML;
++i;
if(i > 20){
i = 0;
document.getElementById('message').innerHTML = innerHTML = "";
}
}
//关闭连接
function closeWebSocket(){
websocket.close();
websocket = null;
}
//发送消息到服务端
function send(){
var message = document.getElementById('text').value;
websocket.send(message);
document.getElementById('text').value = "";
document.getElementById('text').focus();
}
</script>
</body>
</html>