一、概述
作為HTML5新特性之一的WebSocket組件,在實(shí)時(shí)性有一定要求的WEB應(yīng)用開發(fā)中還是有一定用武之地,高版本的IE、Chrome、FF瀏覽器都支持Websocket,標(biāo)準(zhǔn)的Websocket通信是基于RFC6455實(shí)現(xiàn)服務(wù)器端與客戶端握手與消息接發(fā)的。如果對(duì)Websocket通信不是太理解,可以查看RFC文檔即可,簡(jiǎn)單說(shuō)就是通過(guò)發(fā)送HTTP請(qǐng)求,實(shí)現(xiàn)雙方握手,將無(wú)狀態(tài)的HTTP通信協(xié)議進(jìn)一步升級(jí)成有狀態(tài)的通信協(xié)議,同時(shí)Websocket還支持子協(xié)議選項(xiàng)與安全傳輸。標(biāo)準(zhǔn)的websocket連接URL以ws開頭,如果是基于TLS的則以wss開頭。基于Websocket可以很方便的開發(fā)基于web聊天程序,各種網(wǎng)頁(yè)消息通知與推送通知。
如果非要扒一扒Websocket的今生前世的話,還記得最早的基于HTTP輪詢實(shí)現(xiàn)網(wǎng)頁(yè)即時(shí)通信的方式,那種做法比較消耗資源、于是有人改進(jìn)了編程CometD長(zhǎng)連接方式,可是本質(zhì)上還是換湯不換藥,而websocket的出現(xiàn)正好解決了這些問(wèn)題,但是很多瀏覽器的低版本還是不支持websocket,于是還催生了一些基于websocket理念實(shí)現(xiàn)的JS通信框架,其中學(xué)得比較像的有SockJS與socket.io,他們都號(hào)稱支持websocket,然后如果瀏覽器端不支持原生的websocket,它們會(huì)自動(dòng)啟用fallback選項(xiàng)使用其它諸如ajax、Http輪詢、長(zhǎng)輪詢/連接、甚至是flash的socket等機(jī)制實(shí)現(xiàn)模擬websocket的工作方式,但是他們最大的弊端是如果客戶端使用了這些框架,服務(wù)器必須用它們,否則等待開發(fā)者就是一大堆無(wú)法回避的問(wèn)題,同時(shí)很多都是無(wú)解的。主要原因在于它們實(shí)現(xiàn)自己的協(xié)議集,不照它們的格式處理數(shù)據(jù)沒法玩。閑話說(shuō)的有點(diǎn)多。
二、實(shí)現(xiàn)步驟
Tomcat7的高版本中實(shí)現(xiàn)了Websocket服務(wù)器端RFC6455標(biāo)準(zhǔn)協(xié)議,可以跟瀏覽器端websocket進(jìn)行通信,首先要做好如下幾步:
1.安裝高版本JDK – JDK8
2.安裝Tomcat 7.0.64
3.在eclipse中建立一個(gè)動(dòng)態(tài)的web項(xiàng)目
根據(jù)JSR標(biāo)準(zhǔn),Java中實(shí)現(xiàn)websocket的標(biāo)準(zhǔn)接口可以基于注解方式,tomcat也搞好了,只有我們實(shí)現(xiàn)如下代碼,即可創(chuàng)建一個(gè)websocket回聲服務(wù)器:
package com.websocket.demo; import java.io.IOException; import java.nio.ByteBuffer; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; @ServerEndpoint(value = "/echo") public class EchoExample { @OnMessage public void echoTextMessage(Session session, String msg, boolean last) { try { if (session.isOpen()) { System.out.println("received from client message = " + msg); session.getBasicRemote().sendText(msg, last); } } catch (IOException e) { try { session.close(); } catch (IOException e1) { } } } @OnOpen public void openConn(Session session) throws IOException { session.getBasicRemote().sendText("hello web socket"); // means open it } @OnMessage public void echoBinaryMessage(Session session, ByteBuffer bb, boolean last) { System.out.println("send binary message..."); try { if (session.isOpen()) { System.out.println("byte buffer lenghth : " + bb.array().length); System.out.println("byte buffer content: " + ((bb.array()[0]) & 0xff)); System.out.println("byte buffer content: " + ((bb.array()[1]) & 0xff)); System.out.println("byte buffer content: " + ((bb.array()[2]) & 0xff)); session.getBasicRemote().sendBinary(bb, last); } } catch (IOException e) { try { session.close(); } catch (IOException e1) { // Ignore } } } }
如何在tomcat中啟動(dòng)websocket服務(wù)器,首先需要在web.xml添加如下配置:
[listener] [listener-class]org.apache.tomcat.websocket.server.WsContextListener[/listener-class] [/listener]
然后實(shí)現(xiàn)ServerApplicationConfig接口,實(shí)現(xiàn)如下:
創(chuàng)建網(wǎng)頁(yè)echo.html,內(nèi)容如下:
[html] [head] [title>Web Socket Echo Test[/title] [script] var ws = null; var count = 0; function setConnected(connected) { document.getElementById('connect').disabled = connected; document.getElementById('disconnect').disabled = !connected; document.getElementById('echo').disabled = !connected; } function connect() { var target = document.getElementById('target').value; if (target == '') { alert('Please select server side connection implementation.'); return; } if ('WebSocket' in window) { ws = new WebSocket(target); } else if ('MozWebSocket' in window) { ws = new MozWebSocket(target); } else { alert('WebSocket is not supported by this browser.'); return; } ws.onopen = function () { setConnected(true); log('Info: WebSocket connection opened.'); }; ws.onmessage = function (event) { log('Received: ' + event.data);
來(lái)源:gloomyfish的博客