socketio 伺服器推送,socketio伺服器推

來源:互聯網
上載者:User

socketio 伺服器推送,socketio伺服器推
   如果面試官問你:要把伺服器端的資料時時顯示在瀏覽器上怎麼實現?我想有很多人會回答使用Ajax技術定時去訪問一個資源,沒錯,使用Ajax的確能實現,但面試官要的絕對不是這個答案。因為使用Ajax頻繁訪問給服務端造成太大的壓力,所以在大部分情況下都是不取的。面試官想要的答案應該是將伺服器端的資料推送至瀏覽器,這樣只需要保持一個長連結就可以了。

socket.io就能實現資料的時時推送,socket.io(官網:http://socket.io/)是一個跨平台,多種串連方式自動切換時時引擎。要說明的是,socket.io.js只能完成用戶端功能,還需要伺服器端的實現才能真正完成資料的推送。socket.io官方給出的例子服務端使用node.js實現,我想還有很多人對node.js是陌生的(me too)。socket.io服務端實現可以有多種語言,應該說只要能支援socket協議就可以。

下面的例子將給出兩個java語言的服務端實現及其使用樣本。樣本內容很簡單,就是在服務端隨機產生一個座標(包含x,y值),然後將其推送至瀏覽器並顯示。我想會推送一個座標值,推送其它資料應該也不是問題。


第一種實現、netty-socketio,座標為:com.corundumstudio.socketio:netty-socketio:1.7.3(gradle),如果使用的是maven,則座標為:


<groupId>com.corundumstudio.socketio</groupId><artifactId>netty-socketio</artifactId><version>1.7.3</version>

a.服務端代碼:

public class Server {private static List<SocketIOClient> clients = new ArrayList<SocketIOClient>();//用於儲存所有用戶端public static void main(String[] args) throws Exception {Configuration configuration = new Configuration();configuration.setHostname("127.0.0.1");//設定主機名稱configuration.setPort(8082);//設定監聽的連接埠號碼SocketIOServer server = new SocketIOServer(configuration);//根據配置建立伺服器對象server.addConnectListener(new ConnectListener() {//添加用戶端串連監聽器@Overridepublic void onConnect(SocketIOClient client) {System.out.println("connected:SessionId=" + client.getSessionId());clients.add(client);//儲存用戶端}});server.start();System.out.println("server started");Timer timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {Random random = new Random();for(SocketIOClient client : clients) {client.sendEvent("pushpoint", new Point(random.nextInt(100), random.nextInt(100)));//每隔一秒推送一次}}}, 1000, 1000);Object object = new Object();synchronized (object) {object.wait();}}}

b.Point類:

public class Point {private int x;private int y;public Point(int x, int y) {this.x = x;this.y = y;}//getter,setter}

c.html頁面:

<!DOCTYPE html><html><head>    <title>netty-socketio測試</title><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/><script src="socket.io/socket.io-1.0.6.js"></script>    <script src="jquery-1.7.2.min.js"></script><script>$(function(){var socket =  io.connect('http://127.0.0.1:8082');//監聽名為pushpoint的事件,這與服務端推送的那個事件名稱必須一致socket.on("pushpoint", function(data){$('#x').text(data.x);$('#y').text(data.y);});});</script></head><body><div id="display" style="height:50px;background-color:grey;">x=<span id="x">0</span>, y=<span id="y">0</span></div></body></html>

第二種實現、socketio-netty(上面一個是netty-socketio),這個實現在maven中央庫中好像還沒有,該項目託管在google code上,項目地址為:http://code.google.com/p/socketio-netty/,本人是把它下載下來後手動安裝在私服上的。
a.服務端代碼:

public class Server2 {private static List<IOClient> clients = new ArrayList<IOClient>();public static void main(String[] args) throws Exception {SocketIOServer ioServer = new SocketIOServer(new IOHandlerAbs() {@Overridepublic void OnShutdown() {System.out.println("shut down");}@Overridepublic void OnMessage(IOClient client, String eventName) {System.out.println("receive message,eventName=" + eventName);}@Overridepublic void OnDisconnect(IOClient client) {System.out.println("disconnect");System.out.println("disconnect");}@Overridepublic void OnConnect(IOClient client) {System.out.println("connect");clients.add(client);}}, 8088);ioServer.start();System.out.println("server started");Timer timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {Random random = new Random();String data = "{\"x\":" +random.nextInt(100)+ ",\"y\":" +random.nextInt(100)+ "}";BASE64Encoder encoder = new BASE64Encoder();data = encoder.encode(data.getBytes());for(IOClient client : clients) {client.send(formatMessage(data));}}}, 1000, 1000);Object object = new Object();synchronized (object) {object.wait();}}private static String formatMessage(String data) {return String.format(                "5:::{\"%s\":\"%s\",\"%s\":[\"%s\"]}",//socket.io字串格式                "name",                "push",//事件名稱                "args",                data//攜帶的資料                );}}

需要說明的是,該實現不能像上一個實現一樣發送一個對象,只能發送一個字串,而且該字串中還不能包含雙引號(也許還有其它特殊字元)。而推送過程中我們使用的資料格式很可能是JSON,那就肯定有雙引號,所以這裡採取的辦法是對要發送的資料進行BASE64編碼,然後在用戶端解碼回來得到我們想要的資料。

b.html頁面:

<!DOCTYPE html><html><head>    <title>socketio-netty測試</title><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/><script src="socket.io/socket.io-0.9.6.js"></script><script src="crypto-js/core-min.js"></script><script src="crypto-js/enc-base64-min.js"></script><script src="crypto-js/enc-utf16-min.js"></script>    <script src="jquery-1.7.2.min.js"></script><script>$(function(){var host = "http://127.0.0.1:8088";var socket = null;if(/MSIE (\d+.\d+);/.test(navigator.userAgent)){if(/MSIE 10(.\d+);/.test(navigator.userAgent)){socket = io.connect(host);}else{socket = io.connect(host,{transports:['jsonp-polling']}); }} else {socket = io.connect(host,{transports:['websocket','flashsocket','htmlfile','xhr-polling','jsonp-polling']}); }socket.on("push", function(data){var words  = CryptoJS.enc.Base64.parse(data);var point  = CryptoJS.enc.Utf8.stringify(words);point = JSON.parse(point);$('#x').text(point.x);$('#y').text(point.y);});});</script></head><body><div id="display" style="height:50px;background-color:grey;">x=<span id="x">0</span>, y=<span id="y">0</span></div></body></html>

第一個例子中實現的socket.io版本為1.0.6,第二個使用的版本為0.9.6。這兩種服務端實現都是基於netty架構的,但個人覺得還是第一種實現比較好用,省去了編碼的過程,而且封裝程度更高。

範例程式碼工程已託管在GitHub中,使用gradle進行構建,地址為:https://github.com/xtayfjpk/socketio-test。
只要將其撿出即可運行。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.