現在,很多網站為了實現即時通訊(real-time),所用的技術都是輪詢(polling)。輪詢是在特定的的時間間隔(time interval)(如每1秒),由瀏覽器對服務器發出HTTP request,然後由服務器返回最新的數據給客服端的瀏覽器。這種傳統的HTTP request d的模式帶來很明顯的缺點 – 瀏覽器需要不斷的向服務器發出請求(request),然而HTTP request 的header是非常長的,裏面包含的數據可能只是壹個很小的值,這樣會占用很多的帶寬。
而最比較新的技術去做輪詢的效果是Comet – 用了AJAX。但這種技術雖然可達到全雙工通信,但依然需要發出請求(reuqest)。
在 WebSocket API,瀏覽器和服務器只需要要做壹個握手的動作,然後,瀏覽器和服務器之間就形成了壹條快速通道。兩者之間就直接可以數據互相傳送。在此WebSocket 協議中,為我們實現即使服務帶來了兩大好處:
1. Header
互相溝通的Header是很小的-大概只有 2 Bytes
2. Server Push
服務器可以主動傳送數據給客戶端
下面實現壹個簡單PUSH例子如下:
服務端代碼:
public class InitServlet extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 1L;
private static List<MessageInbound> socketList;
public void init(ServletConfig config) throws ServletException {
InitServlet.socketList = new ArrayList<MessageInbound>();
super.init(config);
System.out.println("Server start============");
}
public static List<MessageInbound> getSocketList() {
return InitServlet.socketList;
}
}
public class TestWebSocketServlet extends WebSocketServlet{
private static final Logger log = Logger.getLogger(TestWebSocketServlet.class);
/**
*
*/
private static final long serialVersionUID = 1L;
//存儲鏈接的容器
private static List<WebSocketMessageInbound> connsList = new ArrayList<WebSocketMessageInbound>();
@Override
protected StreamInbound createWebSocketInbound(String subProtocol,HttpServletRequest request) {
// TODO Auto-generated method stub
return new WebSocketMessageInbound();
}
public class WebSocketMessageInbound extends MessageInbound{
@Override
protected void onClose(int status) {
// InitServlet.getSocketList().remove(this);
super.onClose(status);
log.debug("onClose");
InitServlet.getSocketList().remove(this);
}
@Override
protected void onOpen(WsOutbound outbound) {
log.debug("onOpen");
super.onOpen(outbound);
InitServlet.getSocketList().add(this);
}
@Override
protected void onBinaryMessage(ByteBuffer message) throws IOException {
// TODO Auto-generated method stub
log.debug("onBinaryMessage");
}
@Override
protected void onTextMessage(CharBuffer message) throws IOException {
// TODO Auto-generated method stub
log.debug("onTextMessage="+message);
// this.getWsOutbound().writeTextMessage(CharBuffer.wrap("===="));
// this.getWsOutbound().writeTextMessage(message);
//發送給所有鏈接的
for (MessageInbound messageInbound : InitServlet.getSocketList()) {
CharBuffer buffer = CharBuffer.wrap(message);
WsOutbound outbound = messageInbound.getWsOutbound();
outbound.writeTextMessage(buffer);
outbound.flush();
}
}
}
}
web.xml配置
<!-- WebSocket -->
<servlet>
<servlet-name>initServlet</servlet-name>
<servlet-class>com.demo.websocket.InitServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>websocket</servlet-name>
<servlet-class>com.demo.websocket.TestWebSocketServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>websocket</servlet-name>
<url-pattern>/websocket</url-pattern>
</servlet-mapping>
前臺代碼:
<html>
<head>
<title>WebSoket Demo</title>
<script type="text/javascript">
//驗證瀏覽器是否支持WebSocket協議
if (!window.WebSocket) {
alert("WebSocket not supported by this browser!");
}
var ws;
function display() {
//var valueLabel = document.getElementById("valueLabel");
//valueLabel.innerHTML = "";
ws=new WebSocket("ws://localhost:8082/springmvc/websocket");
//監聽消息
ws.onmessage = function(event) {
//valueLabel.innerHTML+ = event.data;
log(event.data);
};
// 打開WebSocket
ws.onclose = function(event) {
//WebSocket Status:: Socket Closed
};
// 打開WebSocket
ws.onopen = function(event) {
//WebSocket Status:: Socket Open
//// 發送壹個初始化消息
ws.send("Hello, Server!");
};
ws.onerror =function(event){
//WebSocket Status:: Error was reported
};
}
var log = function(s) {
if (document.readyState !== "complete") {
log.buffer.push(s);
} else {
document.getElementById("contentId").innerHTML += (s + "\n");
}
}
function sendMsg(){
var msg=document.getElementById("messageId");
//alert(msg.value);
ws.send(msg.value);
}
</script>
</head>
<body onload="display();">
<div id="valueLabel"></div>
<textarea rows="20" cols="30" id="contentId"></textarea>
<br/>
<input name="message" id="messageId"/>
<button id="sendButton" onClick="javascript:sendMsg()" >Send</button>
</body>
< /html>