对于一些对数据实时性要求较高的系统,比如股票行情、在线聊天、微博,实现数据的实时推送是必须的。通常实现实时推送的方式有:
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.java
package 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(); } } } }
test.html
<!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);