關於使用WebSocket的一點經驗

一、 WebSocket介紹:

WebSocket 是 HTML5 開始提供的一種在單個 TCP 連接上進行全雙工通訊的協議。
WebSocket 使得客戶端和服務器之間的數據交換變得更加簡單,允許服務端主動向客戶端推送數據。在 WebSocket API 中,瀏覽器和服務器只需要完成一次握手,兩者之間就直接可以創建持久性的連接,並進行雙向數據傳輸。
在 WebSocket API 中,瀏覽器和服務器只需要做一個握手的動作,然後,瀏覽器和服務器之間就形成了一條快速通道。兩者之間就直接可以數據互相傳送。
現在,很多網站爲了實現推送技術,所用的技術都是 Ajax 輪詢。輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對服務器發出HTTP請求,然後由服務器返回最新的數據給客戶端的瀏覽器。這種傳統的模式帶來很明顯的缺點,即瀏覽器需要不斷的向服務器發出請求,然而HTTP請求可能包含較長的頭部,其中真正有效的數據可能只是很小的一部分,顯然這樣會浪費很多的帶寬等資源。
HTML5 定義的 WebSocket 協議,能更好的節省服務器資源和帶寬,並且能夠更實時地進行通訊。

二、傳統的Ajax 輪詢代碼

下面是script中寫的Ajax輪詢方法
Ajax方法寫好後,要調用Window setInterval() 這個方法,數值以毫秒計算。

function getEvents(){
	$.ajax({
		async: false,
		type: "get",
		url: url,
		dataType: "json",
		success(data) {
		
						//返回後的數據處理。
				)
			}
		}
	})
}
getEvents();			//頁面加載便執行方法
setInterval(function(){
	getEvents();
},15000);				//每15秒執行一次。

三、 WebSocket持續推送。

頁面代碼:

	<input id="text" type="text"/>
	<button onclick="send()">發送消息</button>
	<hr/>
	<button onclick="closeWebSocket()">關閉WebSocket連接</button>
	<hr/>
	<div id="message"></div>
	
	<script>代碼:
		var websocket = null;
		//判斷當前瀏覽器是否支持WebSocket
		if('WebSocket' in window){
			//連接WebSocket節點訪問後臺的URL路徑,002是參數。
			websocket = new WebSocket("ws://localhost:8080/admin/productWebSocket");
		}
		else{
			alert('Not support websocket')
		}
		//連接發生錯誤的回調方法
		websocket.onerror = function(){
			setMessageInnerHTML("error");
		};
		//連接成功建立即執行的方法
		websocket.onopen = function(event){
			setMessageInnerHTML("open");//調用下面的方法。
		}
		//接收到消息的回調方法
		websocket.onmessage = function(event){
			setMessageInnerHTML(event.data);
		//對數據進行處理。
		}
		//連接關閉的回調方法
		websocket.onclose = function(){
			setMessageInnerHTML("close");
		}
		//監聽窗口關閉事件,當窗口關閉時,主動去關閉websocket連接,防止連接還沒斷開就關閉窗口,server端會拋異常。
		window.onbeforeunload = function(){
			websocket.close();
		}
		//將消息顯示在網頁上
		function setMessageInnerHTML(innerHTML){
				document.getElementById('message').innerHTML += innerHTML + '<br/>';
		}
		//發送消息
		function send(){
			var message = document.getElementById('text').value;
			websocket.send(message);
		}
		//關閉連接
		function closeWebSocket(){
			websocket.close();
		}
		

後臺 WebSocket代碼:


@Component
@ServerEndpoint(value = "/admin/productWebSocket", configurator = MyEndpointConfigure.class)
public class ProductWebSocket {
    // 靜態變量,用來記錄當前在線連接數。應該把它設計成線程安全的。
    private static final AtomicInteger OnlineCount = new AtomicInteger(0);
    // concurrent包的線程安全Set,用來存放每個客戶端對應的ProductWebSocket對象。
    private static CopyOnWriteArraySet<ProductWebSocket> webSocketSet = new CopyOnWriteArraySet<ProductWebSocket>();
    // 與某個客戶端的連接會話,需要通過它來給客戶端發送數據
    private Session session;
    private Logger log = LoggerFactory.getLogger(ProductWebSocket.class);

    /**
     * 連接建立成功調用的方法
     */
    @OnOpen
    public void onOpen(@PathParam("userId")String titleId, Session session) {
        log.info("新客戶端連入,用戶id:" + titleId);//titleId 便是後面跟的002參數
        ProductWebSocket client = new ProductWebSocket();
        client.session = session;
        client.webSocketSet = webSocketSet;
        client.carId=titleId;
     	 if("002".equals(titleId)) {
            webSocketSet.add(client); // 加入set中
        }
        System.out.println("-當前在線人數爲:"+getOnlineCount());
    }

    /**
     * 連接關閉調用的方法
     */
    @OnClose
    public void onClose(Session session) {
        log.info("一個客戶端關閉連接");
        for (ProductWebSocket productWebSocket : webSocketSet) {
            if (productWebSocket.session.equals(session)) {
                webSocketSet.remove(productWebSocket);
            }
        }
    }
    /**
     * 收到客戶端消息後調用的方法
     *
     * @param message
     *            客戶端發送過來的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("用戶發送過來的消息爲:"+message);
		//羣發消息
		for(ProductWebSocket item: webSocketSet){
		try {
		item.sendMessage(message);
		} catch (IOException e) {
		e.printStackTrace();
		continue;
		}
}

    /**
     * 發生錯誤時調用
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("websocket出現錯誤");
        error.printStackTrace();
    }

    public void sendMessage(String message) {
        try {
            this.session.getBasicRemote().sendText(message);
            log.info("推送消息成功,消息爲:" + message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 羣發自定義消息
     */
    public static void sendInfo(String message) throws IOException {
        for (ProductWebSocket productWebSocket : webSocketSet) {
            productWebSocket.sendMessage(message);
        }
    }
    public static synchronized int getOnlineCount() {
        return OnlineCount.get();
    }

    public static synchronized void addOnlineCount() {
        OnlineCount.incrementAndGet(); // 在線數加1
    }

    public static synchronized void subOnlineCount() {
        OnlineCount.decrementAndGet(); // 在線數加1
    }

}

以上便是使用WebSocket的一點經驗,代碼多變,方法也不盡相同。僅留作日後參考。
有錯誤還請大家指正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章