html面頁與JAVA通過Socket 通訊
(原)
往常前後端通訊基本都是以ajax請求或是表單做數據交互的,這是一種無狀態的http協議,如果要做tcp協議的數據交互,能想到的技術也就socket了,可如果後端是JAVA,前端如何做socket呢,其實這裏用JSP就行,其實這裏如果都用JDK自帶的socket client 和 socket server 就OK了,如果換成html呢?那麽JAVA就無能為力了,好在有socket.io。下面來看看如何實現吧。
1、你必需知道socket.io實現上就是一個js文件,它可以在這下載。(https://github.com/socketio/socket.io-client)
上面也寫的很清楚了,最簡單的使用方法,也就幾行代碼。
2、你需要知道JAVA端怎麽寫最方便,實現已經有第三方針對於socket.io完成了JAVA端的實現,只用引入JAR包,調用相應的API就行了,它跟socket.io有個相對應的名字,叫netty-socketio。它可以在這裏下載。(https://github.com/mrniko/netty-socketio)
它的文檔裏也寫了一大堆,實際上你要不出錯最快的上手,只需要這一句話就夠了。
netty-socketio的1.6.6版本支持socket.io1.0以下的版本,最新版的netty-socketio支持1.0以上的socket.io版本。
(別混了概念,netty-socketio指的是JAVA端的一個JAR,socket.io指的是一個JS文件)
3.這裏就以最新版本以例。
先寫前端。
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>demo</title> <script src="js/jquery/jquery-1.8.3.min.js" type="text/javascript"></script> <script type="text/javascript" src="js/socket.io/socket.io.js"></script> </head> <body> </body> <script type="text/javascript"> //創建TCP連接 var socket = io.connect(‘http://192.168.0.104:8998‘); //連接成功後會監聽到 socket.on(‘connect‘,function() { output(‘<span>連接成功</span>‘); }); socket.on(‘connecting‘,function() { output(‘<span>正在連接...</span>‘); }); socket.on(‘disconnect‘,function() { output(‘<span>斷開連接! </span>‘); }); socket.on(‘reconnecting‘,function() { output(‘<span>正在重連...</span>‘); }); socket.on(‘reconnect‘,function() { output(‘<span>成功重連!</span>‘); }); socket.on(‘connect_failed‘,function() { output(‘<span>連接失敗!</span>‘); }); //想要斷開連接調用此方法 function sendDisconnect() { socket.disconnect(); } //下面的testMessage是自定義的。 socket.emit(‘testMessage‘, ‘Hello‘,function(){ output(‘<span>‘ + data + ‘</span>‘); }); //socket.emit(‘testMessage‘, ‘你好‘,function(){ // output(‘<span>‘ + data + ‘</span>‘); //}); //這裏是監聽服務端返回的testMessage事件 //socket.on(‘testMessage‘,function(data){ // output(‘<span>‘ + data + ‘</span>‘); //}); function output(message) { var currentTime = "<span class=‘time‘ >" + new Date().toLocaleString() + "</span>"; var element = $("<div>" + currentTime + " " + message + "</div>"); $(‘body‘).prepend(element); } </script> </html>
我們叫這個頁面為demo.html
然後再寫JAVA後端
只需要二個類,一個是開啟socket服務的類,一個是監聽的類,這裏只監聽客戶端的連接,斷開和發送testMessage消息。
package com.ewin.ccr; import com.corundumstudio.socketio.AckRequest; import com.corundumstudio.socketio.SocketIOClient; import com.corundumstudio.socketio.SocketIOServer; import com.corundumstudio.socketio.listener.ConnectListener; import com.corundumstudio.socketio.listener.DataListener; import com.corundumstudio.socketio.listener.DisconnectListener; public class SocketListener implements ConnectListener ,DisconnectListener,DataListener<String>{ private SocketIOServer server; public SocketListener(SocketIOServer server){ this.server = server; } @Override public void onConnect(SocketIOClient client) { Integer clientSize = server.getAllClients().size(); System.out.println("剛連上一個客戶端,總共有" + clientSize + "客戶端連接成功。"); } @Override public void onDisconnect(SocketIOClient client) { Integer clientSize = server.getAllClients().size(); System.out.println("剛離開一個客戶端,總共有" + clientSize + "客戶端連接成功。"); } @Override public void onData(SocketIOClient client, String data, AckRequest ackSender) throws Exception { System.out.println("剛有一個數據從客戶端過來" + data); ackSender.sendAckData("服務端消息收到!-----"); } }
以上為監聽類
package com.ewin.ccr; import com.corundumstudio.socketio.Configuration; import com.corundumstudio.socketio.SocketIOServer; import com.ewin.ccr.listener.TroutingWipHEventListener; import com.ewin.ccr.util.SocketConfig; public class SocketServer { public static void main(String[] args) { Configuration config = new Configuration(); config.setHostname(SocketConfig.getValue("host")); config.setPort(Integer.parseInt(SocketConfig.getValue("port"))); SocketIOServer server = new SocketIOServer(config); SocketListener socketListener = new SocketListener(server); //客戶端連接上時觸發 server.addConnectListener(socketListener); //監聽客戶端消息 //工單產品執行監控表頭數據,只發一次,需要由客戶端請求後發送 server.addEventListener("testMessage", String.class, new TroutingWipHEventListener()); //客戶斷連接斷開時觸發 server.addDisconnectListener(socketListener); //啟動服務 server.start(); // server.stop(); } }
以上為開啟socket服務的類
運行SocketServer這個類
然後進入我們的demo頁面,你會看到如下信息
後臺會是這樣的。
然後我們嘗試關閉頁面。後臺會變成這樣。
我們嘗試關掉JAVA服務,頁面會變成這樣。
其實,這還沒完,這裏不知是BUG,還是什麽原因,會有一個問題。
看到頁面這個地方沒有
現在我們來換一下,發送一個中文的"你好"給後臺,我們需要把上面的註釋取消,把下面的註釋放開,改成這樣
然後我們把demo.html頁面刷新一下,關掉,再重開(這樣是為了使修改的JS生效)
OK,前面沒有問題,再看下我們的二個中文字“你好”過去沒有。
看到沒,後端是亂碼,估計這種問題的第一反應,可能絕大數程序員想的跟我一樣,轉碼出了問題,於是各種前後端編碼,字符集的檢查,但是你會發現,以前出現這種問題時,能用上的轉碼,切換字符集的招數都用遍了, 這裏依然無效。
經過我一天的摸索,得到一個好消息與一個壞消息。
先說壞的,百度有人說是socket.io版本不夠新,今天是2017年6月4號,最新版是6月2號的2.0.2版本,我試了一下最新的,問題依然存在。
好消息是我找到了問題的解決辦法,但是過於暴力。
看下面這段代碼:
跟剛才的本質沒有變,只是延遲0.5秒發送消息,我們再次刷新demo.html頁面,來看下後臺的反應。
看到沒,中文傳送過來了。
那有人可能就要問了,如果做一個即時通訊之類的,那豈不是每次發送消息都要等上半秒鐘,其實不是這樣的,經過我多次的測試,只有在連接剛建立完成以後的一小段時間內發送中文才會有這個問題(上面其實是連建立後等了0.5秒發送的消息,實際上測的是延遲0.2秒以上再發送消息 ,後面收到中文的概率已經很大了),後面再發送都不會有這個問題。
html面頁與JAVA通過Socket 通訊