基于tomcat運行HTML5 WebSocket echo例子
一:概述
作為HTML5新特性之一的WebSocket組件,在實時性有一定要求的WEB應用開發中還是有一定用武之地,高版本的IE、Chrome、FF瀏覽器都支持Websocket,標準的Websocket通信是基于RFC6455實現服務器端與客戶端握手與消息接發的。如果對Websocket通信不是太理解,可以查看RFC文檔即可,簡單說就是通過發送HTTP請求,實現雙方握手,將無狀態的HTTP通信協議進一步升級成有狀態的通信協議,同時Websocket還支持子協議選項與安全傳輸。標準的websocket連接URL以ws開頭,如果是基于TLS的則以wss開頭。基于Websocket可以很方便的開發基于web聊天程序,各種網頁消息通知與推送通知。
如果非要扒一扒websocket的今生前世的話,還記得最早的基于HTTP輪詢實現網頁即時通信的方式,那種做法比較消耗資源、于是有人改進了編程CometD長連接方式,可是本質上還是換湯不換藥,而websocket的出現正好解決了這些問題,但是很多瀏覽器的低版本還是不支持websocket,于是還催生了一些基于websocket理念實現的JS通信框架,其中學得比較像的有SockJS與socket.io,他們都號稱支持websocket,然后如果瀏覽器端不支持原生的websocket,它們會自動啟用fallback選項使用其它諸如ajax、Http輪詢、長輪詢/連接、甚至是flash的socket等機制實現模擬websocket的工作方式,但是他們最大的弊端是如果客戶端使用了這些框架,服務器必須用它們,否則等待開發者就是一大堆無法回避的問題,同時很多都是無解的。主要原因在于它們實現自己的協議集,不照它們的格式處理數據沒法玩。閑話說的有點多。
二 : 實現步驟
Tomcat7的高版本中實現了websocket服務器端RFC6455標準協議,可以跟瀏覽器端websocket進行通信,首先要做好如下幾步:
1. 安裝高版本JDK – JDK8
2. 安裝tomcat 7.0.64
3. 在eclipse中建立一個動態的web項目
根據JSR標準,Java中實現websocket的標準接口可以基于注解方式,tomcat也搞好了,只有我們實現如下代碼,即可創建一個websocket回聲服務器:
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 } } }
}</pre>
如何在tomcat中啟動websocket服務器,首先需要在web.xml添加如下配置:
<listener> <listener-class>org.apache.tomcat.websocket.server.WsContextListener</listener-class> </listener>
然后實現ServerApplicationConfig接口,實現如下:
/ */ package com.config.websocket.client;import java.util.HashSet; import java.util.Set;
import javax.websocket.Endpoint; import javax.websocket.server.ServerApplicationConfig; import javax.websocket.server.ServerEndpointConfig;
public class ScanWebSocketSeverConfig implements ServerApplicationConfig {
@Override public Set<ServerEndpointConfig> getEndpointConfigs(Set<Class<? extends Endpoint>> scanned) { Set<ServerEndpointConfig> result = new HashSet<ServerEndpointConfig>();
/ if (scanned.contains(EchoWsChatSever.class)) { result.add(ServerEndpointConfig.Builder.create(EchoWsChatSever.class, "/echo").build()); }/ return result; }
@Override public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scanned) { Set<Class<?>> results = new HashSet<Class<?>>(); for (Class<?> clazz : scanned) { if (clazz.getPackage().getName().startsWith("com.websocket.")) { System.out.println("find end point : " + clazz.getName()); results.add(clazz); } } return results; }
}</pre>
創建網頁echo.html,內容如下:
<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); if(event.data instanceof ArrayBuffer) { var bytes = new Uint8Array(event.data); alert(bytes.length + " : " + bytes[0]); } }; ws.onclose = function (event) { setConnected(false); log('Info: WebSocket connection closed, Code: ' + event.code + (event.reason == "" ? "" : ", Reason: " + event.reason)); }; } function disconnect() { if (ws != null) { ws.doClose(); ws = null; } setConnected(false); } function echo() { if (ws != null) { var message = document.getElementById('message').value; log('Sent: ' + message); ws.send(JSON.stringify({'textMessage': message})); count++ } else { alert('WebSocket connection not established, please connect.'); } } function log(message) { var echomsg = document.getElementById('echomsg'); var p = document.createElement('p'); p.style.wordWrap = 'break-word'; p.appendChild(document.createTextNode(message)); echomsg.appendChild(p); while (echomsg.childNodes.length > 25) { echomsg.removeChild(console.firstChild); } echomsg.scrollTop = console.scrollHeight; } document.addEventListener("DOMContentLoaded", function() { // Remove elements with "noscript" class - <noscript> is not allowed in XHTML var noscripts = document.getElementsByClassName("noscript"); for (var i = 0; i < noscripts.length; i++) { noscripts[i].parentNode.removeChild(noscripts[i]); } }, false);
</script> </head> <body> <div> <h4>URL - ws://localhost:8080/websocket/echo</h4> <input id="target" type="text" size="40" style="width: 350px" /> </div> <div> <button id="connect" onclick="connect();">Connect</button> <button id="disconnect" disabled="disabled" onclick="disconnect();">Disconnect</button> </div> <div> <textarea id="message" style="width: 350px">Here is a message!</textarea> </div> <div> <button id="echo" onclick="echo();" disabled="disabled">Echo message</button> </div> <div id="echomsg"> </div> </body> </html></pre>三 :運行與測試
打包部署到tomcat之后,啟動chrom瀏覽器,輸入地址:
http://localhost:8080/websocket/echo.html
![]()
后來,我還發現,tomcat實現websocket服務器端居然不支持子協議
跟3W上的測試URL結果不一樣。
來自:http://blog.csdn.net/jia20003/article/details/48751847