WebSocket,實現簡單的廣播功能
阿新 • • 發佈:2019-02-12
改變現在,從通訊開始
傳統的前端和後端的資料互動是使用輪詢方法,會佔用大量資源。在如今高速發展的時代,一種能提升效率的方法或者說新技術便顯得尤為重要。
websocket便是這樣一種技術,有關於它的更多的一些細節,大家可以自行百度。(本部落格部分程式碼來源自網上,向前輩們致敬)
這裡看一下廣播的演示結果:
不寫程式碼,終究是紙上談兵
這裡只是展示websocket的一個小demo,並未對介面做過多要求。於是只設計了一個簡單的傳送訊息文字框和按鈕。載入頁面時初始化socket,點選按鈕觸發socket.send(msg)方法便可。由於是多客戶端廣播,每一個socket在連線伺服器時需要加上自己相應的id引數。(這裡生成id引數方法並不推薦)
<%-- Created by IntelliJ IDEA. --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>WebSocket 客戶端</title>
</head>
<body>
<div >
<div class="main">
<input name="message" id="msg" onkeydown="if (event.keyCode==13) sendMsg()"/>
<button onclick="sendMsg()">傳送</button>
</div>
</div>
<script src="resource/js/jquery.js" type="text/javascript" charset="utf-8"></script>
<script src="resource/js/socket.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
var uid = getRandomWithoutRepeat([1,2,3,4,5,6,7,8,9,10]);//獲取當前賬戶的id;
var url="ws://127.0.0.1:8080/webSocketServer/"+uid[0];
var socket = getSocket(url);
bindMethod(socket);
function sendMsg() {
Log("傳送:"+$("#msg").val(),"INFO");
socket.send($("#msg").val());
$("#msg").val("")
}
window.onbeforeunload = function() {
socket.close();
};
/**
* 建立隨機數
* @param Min
* @param Max
* @returns {*}
* @constructor
*/
function getRandom(Min,Max){
var Range = Max - Min;
var Rand = Math.random();
return(Min + Math.round(Rand * Range));
}
/**
* 獲取不重複的隨機數
* @param arr
* @returns {Array}
*/
function getRandomWithoutRepeat(arr){
var temp=[]; //temp存放生成的隨機陣列
for (var i=0;i<arr.length;i++)
{
var num=Math.floor(Math.random()*arr.length); //生成隨機數num
temp.push(arr[num]); //獲取arr[num]並放入temp
arr.splice(num,1);
}
return temp;
}
</script>
</body>
</html>
可以發現上述介面部分引入了socket.js檔案,這個是我自己抽象出來的一部分可供重用的方法部分,比如說列印日誌和建立websocket的程式碼。
/**
* Created by zipple on 2017/9/28.
* 建立web socket 物件
* 定義相關方法
*/
/**
* 建立socket物件
* @param url
* @returns {WebSocket}
*/
function getSocket(url) {
if(typeof(WebSocket) == "undefined") { //此處判斷支援Android
alert("您的瀏覽器不支援WebSocket");
}
Log("建立socket物件","OK");
return new WebSocket(url);
}
/**
* 為建立的socket物件繫結相關方法
* @param ws
* @param elements 獲取資訊的地方
*/
function bindMethod(ws) {
ws.onopen = function () {
Log("連線成功","OK")
};
ws.onmessage = WSonMessage;
ws.onclose = WSonClose;
ws.onerror = WSonError;
}
/**
* 獲取資料
* @param event
*/
function WSonMessage(event) {
Log("獲取到資訊:"+event.data,"OK");
var div = "<div>"+event.data+"</div>";
$("body").prepend($(div))
}
/**
* 關閉連線
*/
function WSonClose() {
Log("連線關閉。", "ERROR");
}
/**
* 連結異常
*/
function WSonError() {
Log("WebSocket錯誤。", "ERROR");
}
/**
* 在控制檯列印資料
* @param msg
* @param type
*/
function Log(msg,type) {
switch (type){
case 0 :
type="ERROR";
break;
case 1:
type="OK";
break;
case 2:
type="WARNING";
break;
default:
type="INFO"
}
console.log(type+":"+msg+" at "+getNowFormatDate());
}
/**
* 獲取系統當前時間
* @returns {string}
*/
function getNowFormatDate() {
var currentdate="error occurred in getNoeFormatDate";
var date = new Date();
var seperator1 = "-";
var seperator2 = ":";
var month = date.getMonth() + 1;
var strDate = date.getDate();
if (month >= 1 && month <= 9) {
month = "0" + month;
}
if (strDate >= 0 && strDate <= 9) {
strDate = "0" + strDate;
}
currentdate = date.getFullYear() + seperator1 + month + seperator1 + strDate
+ " " + date.getHours() + seperator2 + date.getMinutes()
+ seperator2 + date.getSeconds();
return currentdate;
}
後臺:接收連線請求,儲存session,遍歷物件,轉發msg
為了實現使用者的廣播(即將某個使用者傳送到伺服器端的資訊轉發至所有使用者)功能,我們需要在接收到使用者websocket連線請求時儲存當前使用者的session,用於轉發資料。
因為這只是一個簡單的demo入門,便不再考慮其他的相關安全操作,下線判斷等等。
package webSocket;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
/**
* 多個使用者之間的通訊
*/
@ServerEndpoint("/webSocketServer/{userId}")
public class WebSocketServer {
private Session session;
private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();
/**
* 連線建立成功呼叫的方法
* @param session 可選的引數。session為與某個客戶端的連線會話,需要通過它來給客戶端傳送資料
*/
@OnOpen
public void onOpen(@PathParam("userId") String userId,Session session){
System.out.println("Client connected "+userId);//在這裡儲存使用者
this.session =session;
webSocketSet.add(this);
}
/**
* 連線關閉呼叫的方法
*/
@OnClose
public void onClose(@PathParam("userId") String userId){
System.out.println("Connection closed");
}
/**
* 收到客戶端訊息後呼叫的方法
* @param message 客戶端傳送過來的訊息
*/
@OnMessage
public void onMessage(@PathParam("userId") String userId,String message) throws IOException {
System.out.println("伺服器接收使用者"+userId+"訊息: " + message);
for (WebSocketServer ws: webSocketSet){
ws.session.getBasicRemote().sendText("伺服器回覆:"+message);
}
}
/**
* 發生錯誤時呼叫
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error){
error.printStackTrace();
}
}
好吧!
其實是寫這篇部落格的時候太困了!
堅持不住了,就直接把所有原始碼貼上來了。
沒有做過多解釋,請同行見諒。
你逃避的北上廣,是我曾嚮往過的遠方