一、WebSocket簡介
對於一些對資料即時性要求較高的系統,例如股票行情、線上聊天、微博,實現資料的即時推送是必須的。通常實現即時推送的方式有:
1、輪詢:隔一段時間發送資料(如:webqq)
2、socket:以往普通的網頁是不支援socket#接收訊息的。可以透過flash或applet來作為socket的客戶端
3、長連線:指在一個TCP連線上可以連續傳送多個資料包,在TCP連線維持期間,如果沒有資料包發送,則需要雙方發檢測包以維持此連接,一般需要自己做
線上維持。
-------------------------------------------- --------------------------------------------------
html5透過window.WebSocket(firefox下是window.MozWebSocket)提供了一種非http的雙向連接,這個連接是即時的更是永久的,除非被顯示colse。
這表示只要客戶端打開一個Socket並且請求建立了連接(just once),服務端就能即時接收並發送訊息,不需要手動偵測和維持狀態。
WebSocket提供的方法和屬性可以在firebug中輸入Window.WebSocket.prototype看到。
接下去的程式碼列出了基本的使用想法:
var location = "ws://localhost:port/serlet/xxx"; //服务端处理的servlet var webSocket = new WebSocket(location); //webSocket.readyState var readyStates = { "CONNECTING":"正在连接“, ”OPEN“ : "已建立连接", "CLOSING":"正在关闭连接", "CLOSED":"已关闭连接" } webSocket.send(data);//发送数据到服务端,目前只支持文本类型。JSON.stringify(data);JSON.parse(data); webSocket.onMessage = function(event){ var data = event.data;//从服务端过来的数据 } webSocket.onOpen = function(event){ //开始通信 } webSocket.onClose = function(event){ //结束通信 } webSocket.close();
二、一個基於jetty(java伺服器)的範例
# 目前Apache還不支援WebSocket,各種語言都有各自的方式可以實現它,這裡在Java中實現了。
步驟一:下載一個jetty,解壓縮放在任何磁碟下方。 jetty7以上才支援WebSocket,下載網址:download.eclipse.org/jetty/stable-7/dist/
步驟二:下載eclipse(不建議使用MyEclipse,比較麻煩,需要安裝其他的外掛程式),必須支援jetty7,版本是越高越好。
步驟三:在eclipse中安裝插件,help---Install new software...----url為:eclipse-jetty.sourceforge.net/update/
步驟四:新建一個Dynamic Web Project
###目錄結構如下 步驟五:拷入以下代碼:
TailorWebSocketServlet.javapackage com.test; import java.io.IOException; import java.util.Date; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.websocket.WebSocket; import org.eclipse.jetty.websocket.WebSocketServlet; public class TailorWebSocketServlet extends WebSocketServlet { private static final long serialVersionUID = -7289719281366784056L; public static String newLine = System.getProperty("line.separator"); private final Set<TailorSocket> _members = new CopyOnWriteArraySet<TailorSocket>(); private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); public void init() throws ServletException { super.init(); executor.scheduleAtFixedRate(new Runnable() { public void run() { System.out.println("Running Server Message Sending"); for(TailorSocket member : _members){ System.out.println("Trying to send to Member!"); if(member.isOpen()){ System.out.println("Sending!"); try { member.sendMessage("from server : happy and happiness! "+new Date()+newLine); } catch (IOException e) { e.printStackTrace(); } } } } }, 2, 2, TimeUnit.SECONDS); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { getServletContext().getNamedDispatcher("default").forward(request, response); } public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) { return new TailorSocket(); } class TailorSocket implements WebSocket.OnTextMessage { private Connection _connection; public void onClose(int closeCode, String message) { _members.remove(this); } public void sendMessage(String data) throws IOException { _connection.sendMessage(data); } public void onMessage(String data) { System.out.println("Received: "+data); } public boolean isOpen() { return _connection.isOpen(); } public void onOpen(Connection connection) { _members.add(this); _connection = connection; try { connection.sendMessage("onOpen:Server received Web Socket upgrade and added it to Receiver List."); } catch (IOException e) { e.printStackTrace(); } } } }
<!DOCTYPE HTML> <html> <head> <meta charset = "utf-8"/> <title>Chat by Web Sockets</title> <script type='text/javascript'> if (!window.WebSocket) alert("window.WebSocket unsuport!"); function $() { return document.getElementById(arguments[0]); } function $F() { return document.getElementById(arguments[0]).value; } function getKeyCode(ev) { if (window.event) return window.event.keyCode; return ev.keyCode; } var server = { connect : function() { var location ="ws://localhost:8888/servlet/a"; this._ws =new WebSocket(location); this._ws.onopen =this._onopen; this._ws.onmessage =this._onmessage; this._ws.onclose =this._onclose; }, _onopen : function() { server._send('send to server : websockets are open for communications!'); }, _send : function(message) { if (this._ws) this._ws.send(message); }, send : function(text) { if (text !=null&& text.length >0) server._send(text); }, _onmessage : function(m) { if (m.data) { var messageBox = $('messageBox'); var spanText = document.createElement('span'); spanText.className ='text'; spanText.innerHTML = m.data; var lineBreak = document.createElement('br'); messageBox.appendChild(spanText); messageBox.appendChild(lineBreak); messageBox.scrollTop = messageBox.scrollHeight - messageBox.clientHeight; } }, _onclose : function(m) { this._ws =null; } }; </script> <style type='text/css'> div { border: 0px solid black; } div#messageBox { clear: both; width: 40em; height: 20ex; overflow: auto; background-color: #f0f0f0; padding: 4px; border: 1px solid black; } div#input { clear: both; width: 40em; padding: 4px; background-color: #e0e0e0; border: 1px solid black; border-top: 0px } div.hidden { display: none; } span.alert { font-style: italic; } </style> </head> <body> <div id='messageBox'></div> <div id='input'> <div> <input id='connect' type='submit' name='Connect' value='Connect' /> </div> </div> <script type='text/javascript'> $('connect').onclick =function(event) { server.connect(); returnfalse; }; </script> <p> JAVA Jetty for WebSocket </p> </body> </html>
## 步驟六:
# 下的效果: 恭喜你,到這兒就算為success了!
三、效能
對於這種類型的連接,各種伺服器需要消耗的效能也不同,java下可以透過JDK的bin目錄下的Jconsole來查看,單一連線記憶體消耗在2.5M左右,但對於並發量還沒有做測試。這裡不貼圖了
以上是html5 WebSocket在jetty7中實現的程式碼分享的詳細內容。更多資訊請關注PHP中文網其他相關文章!