1. 程式人生 > >websocket基礎:websocket使用示例及學習資料

websocket基礎:websocket使用示例及學習資料

介紹

Web Sockets的目標是在一個單獨的持久連線上提供全雙工、雙向通訊。在JavaScript中建立了Web Socket之後,會有一個HTTP請求傳送到瀏覽器以發起連線。在取得伺服器響應後,建立的連線會使用HTTP升級從HTTP協議交換為Web Socket協議。也就是說,使用標準的HTTP伺服器無法實現Web Sockets,只有支援這種協議的專門伺服器才能正常工作。

由於Web Sockets使用了自定義的協議,所以URL模式也略有不同。未加密的連線不再是http://,而是ws://;加密的連線也不是https://,而是wss://。在使用Web Socket URL時,必須帶著這個模式,因為將來還有可能支援其他模式。

使用自定義協議而非HTTP協議的好處是,能夠在客戶端和伺服器之間傳送非常少量的資料,而不必擔心HTTP那樣位元組級的開銷。由於傳送的資料包很小,因此Web Sockets非常適合移動應用。畢竟對移動應用而言,頻寬和網路延遲都是關鍵問題。使用自定義協議的缺點在於,指定協議的時間比制定JavaScript API的時間還要長。

示例教程

學習WebSocket最好的資料就是官方給的demo,比如tomcat容器給的examples。無論你的tomcat中有沒有examples示例檔案,啟動tomcat伺服器後,開啟localhost:8080都能看到這樣的部分:

圈紅的部分就是tomcat給出的該容器支援的API的示例。點開連線,可能會看到

說明在你的tomcat中沒有examples示例專案。也就是在tomcat安裝目錄下的webapps資料夾中沒有examples資料夾,到官網上下載一份對應版本的tomcat,解壓後複製examples資料夾到TOMCAT_HOME(安裝目錄)下的webapps中,重啟伺服器,再次訪問localhost:8080,點選Examples連線,可以看到在頁面中有這樣的幾個示例專案:

第三個就是學習WebSocket要用到的示例專案,可以到資料夾中檢視java原始碼,位置:TOMCAT_HOME/webapps/examples/WEB-INFO/classes/websocket,xhtml程式碼:TOMCAT_HOME/webapps/examples/websocket。

沒有下載examples檔案可以線上檢視tomcat示例:http://www.4371.cn/

視訊學習下載(尚學堂-高明鑫-websocket-01-08)

視訊:百度雲網盤連結:http://pan.baidu.com/s/1bp9imsv 密碼:rokz

示例專案下載

自己也將tomcat examples中的兩個示例專案匯入了eclipse中,環境:JDK1.7,tomcat7.maven+eclipse

已經打包,下載解壓後將websocket\target下的websocket.war包直接放到tomcat下的webapps中,啟動伺服器後訪問http://localhost:8080/websocket/websocket/echo/echo.html

和http://localhost:8080/websocket/websocket/chat/chat.html即可,分別是tomcat的echo和chat示例。環境已經搭建好可以直接執行。

使用講解

使用websocket完成的目標是在客戶和伺服器之間建立一個雙向可通的通道。既然是雙向的,那麼就要求要對伺服器和客戶端兩部分進行程式設計。

伺服器

伺服器中的程式碼websocket部分也分為兩部分,一個是配置,另一個是服務。

配置的話比較簡單,就是在專案啟動時檢測websocket服務類。在tomcat的示例中有介面式的websocket也有註解式的websocket兩種示例。在上面自己整理的專案中只有註解式的,感覺註解比較簡潔。

註解式的實現配置檔案只需實現javax.websocket.server.ServerApplicationConfig介面即可,是websocket的核心配置類,該介面也只有兩個需要實現的方法,程式碼:

public class WSCoreConfig implements ServerApplicationConfig{
 
    public Set<ServerEndpointConfig> getEndpointConfigs(
            Set<Class<? extends Endpoint>> scanned) {
        return null;
    }
 
    //註解的方式
    public Set<Class<?>>getAnnotatedEndpointClasses(Set<Class<?>> scanned) {
        System.err.println("===== START CONFIG=====\nscannedsize:" + scanned.size());
        return scanned;
    }
}
對於服務,就是用來處理通道各種狀態(開啟、異常、關閉)及收發資訊的類,用來完成websocket的基本操作:

1.  開啟連線

2.  伺服器端接收資料

3.  伺服器端給客戶端傳送資料

4.  處理異常

主要需要用到的註解:@OnOpen@OnClose@OnMessage@OnError

分別對應通道開啟、通道關閉、收發資訊、異常。

簡單的示例程式碼也是比較簡單的:

@ServerEndpoint(value="/ws/echo/echoServer/chat")
public class ChatAnnotation {
 
 
    private static final String GUEST_PREFIX = "Guest";
    private static final AtomicInteger connectionIds = new AtomicInteger(0);
    private static final Set<ChatAnnotation> connections =
            new CopyOnWriteArraySet<ChatAnnotation>();
 
    private final String nickname;
    private Session session;
 
    public ChatAnnotation() {
        nickname = GUEST_PREFIX + connectionIds.getAndIncrement();
    }
 
 
    @OnOpen
    public void start(Session session) {
        this.session = session;
        connections.add(this);
        String message = String.format("* %s %s", nickname, "has joined.");
        broadcast(message);
    }
 
 
    @OnClose
    public void end() {
        connections.remove(this);
        String message = String.format("* %s %s",
                nickname, "has disconnected.");
        broadcast(message);
    }
 
 
    @OnMessage
    public void incoming(String message) {
        broadcast(nickname + " : " + message);
    }
 
 
 
 
    @OnError
    public void onError(Throwable t) throwsThrowable {
   
    }
 
 
    private static void broadcast(String msg) {
        for (ChatAnnotation client : connections) {
            try {
                synchronized (client) {
                    client.session.getBasicRemote().sendText(msg);
                }
            } catch (IOException e) {
                connections.remove(client);
                try {
                    client.session.close();
                } catch (IOException e1) {
                    // Ignore
                }
                String message = String.format("* %s %s",
                        client.nickname, "has been disconnected.");
                broadcast(message);
            }
        }
    }
}
程式碼講解:

開始的@ServerEndpoint(value="/ws/echo/echoServer/chat")表示該服務類的URI。在前臺連線該服務時用到的url為:ws://localhost:8080 /websocket/ws/echo/echoServer/chat。該類中定義了一個靜態方法broadcast(),為廣播客戶端傳送來的資訊。client.session.getBasicRemote().sendText(msg);該程式碼行為傳送資訊的主要程式碼,向客戶端傳送訊息。

該類中的其它幾個方法的宣告上可以看到@onXXX,表示該方法在何時得到呼叫。

客戶端

客戶端的程式碼主要是websocket物件。要建立WebSocket,先例項一個WebSocket物件並傳入要連線的URL:

var socket = newWebSocket(“ws://localhost:8080 /websocket/ws/echo/echoServer/chat”);

注意,必須給WebSocket建構函式傳入絕對URL。同源策略對WebSockets不適用,因此可以通過它開啟到任何站點的連線。至於是否會與某個域中的頁面通訊,則完全取決於度武器。(通過握手資訊就可以知道請求來自何方。)

例項化了WebSocket物件後,瀏覽器就會馬上嘗試建立連線。WebSocket有一個表示當前狀態的readState屬性,如下所示:

WebSocket.OPENING(0):正在建立連線。

WebSocket.OPEN(1):已經建立鍵連線。

WebSocket.CLOSING(2):正在關閉連線。

WebSocket.CLOSE(3):已經關閉連線。

WebSocket沒有readystatechange事件;不過,它有其他事件,對應著不同的狀態。readyState的值永遠從0開始。

要關閉Web Socket連線,可以在任何時候呼叫close()方法。

socket.close();

傳送和接收資料

Web Socket開啟之後,就可以通過連線傳送和接收資料。要向伺服器傳送資料,使用send()方法並傳入任意字串,例如:

var socket = newWebSocket(“ws://localhost:8080 /websocket/ws/echo/echoServer/chat”);

socket.send(“HelloWorld”);

因為Web Socket只能通過連線傳送純文字資料,所以對於複雜的資料結構,在通過連線傳送之前,必須進行序列化。

當服務端發來訊息時,WebSocket物件就會觸發message事件。這個事件與其他傳遞訊息的協議類似,也是把返回的資料儲存在event.data屬性中。

其他事件

WebSocket物件還有其他三個事件,在連續生命週期的不同階段觸發。

open:在成功建立連線時觸發。

error:在發生錯誤時觸發,連線不能持續。

close:在連線關閉時觸發。

客戶端JS程式碼:

var ws = null;

function setConnected(connected) {
    document.getElementById('connect').disabled = connected;
    document.getElementById('disconnect').disabled = !connected;
    document.getElementById('echo').disabled = !connected;
}

function connect() {
    var target = document.getElementById('target').value;
    if (target == '') {
        alert('Please select server side connection implementation.');
        return;
    }
    if ('WebSocket' in window) {
        ws = new WebSocket(target);
    } else if ('MozWebSocket' in window) {
        ws = new MozWebSocket(target);
    } else {
        alert('WebSocket is not supported by this browser.');
        return;
    }
    ws.onopen = function () {
        setConnected(true);
        log('Info: WebSocket connection opened.');
    };
    ws.onmessage = function (event) {
        log('Received: ' + event.data);
    };
    ws.onclose = function (event) {
        setConnected(false);
        log('Info: WebSocket connection closed, Code: ' + event.code + (event.reason == "" ? "" : ", Reason: " + event.reason));
    };
}

function disconnect() {
    if (ws != null) {
        ws.close();
        ws = null;
    }
    setConnected(false);
}

function echo() {
    if (ws != null) {
        var message = document.getElementById('message').value;
        log('Sent: ' + message);
        ws.send(message);
    } else {
        alert('WebSocket connection not established, please connect.');
    }
}

function updateTarget(target) {
    if (window.location.protocol == 'http:') {
        document.getElementById('target').value = 'ws://' + window.location.host + target;
    } else {
        document.getElementById('target').value = 'wss://' + window.location.host + target;
    }
}

function log(message) {
    var console = document.getElementById('console');
    var p = document.createElement('p');
    p.style.wordWrap = 'break-word';
    p.appendChild(document.createTextNode(message));
    console.appendChild(p);
    while (console.childNodes.length > 25) {
        console.removeChild(console.firstChild);
    }
    console.scrollTop = console.scrollHeight;
}


document.addEventListener("DOMContentLoaded", function() {
    // Remove elements with "noscript" class - <noscript> is not allowed in XHTML
    var noscripts = document.getElementsByClassName("noscript");
    for (var i = 0; i < noscripts.length; i++) {
        noscripts[i].parentNode.removeChild(noscripts[i]);
    }
}, false);
程式碼講解:

首先定義了一個名為ws的全域性變數,建立WebSocket例項時傳入了URL引數:

ws = new WebSocket(target);

方法connect()為關鍵方法,例項WebSocket物件,並指定了open、message、error、close事件的處理程式。在該方法中做了瀏覽器相容處理:

    if ('WebSocket' in window) {
        ws = new WebSocket(target);
    } else if ('MozWebSocket' in window) {
        ws = new MozWebSocket(target);
    } else {
        alert('WebSocket is not supported by thisbrowser.');
        return;
}
其他方法說明:

setConnected()設定頁面按鈕的狀態(已經連線時,連線按鈕禁用、啟用斷開連線按鈕和訊息按鈕……)

disconnect()斷開連線:ws.close();

echo()列印訊息到頁面。

javax.websocketAPI

關於介面式的websocket可參考tomcat官方示例,若在學習或專案搭建過程中有什麼問題可評論或郵件我的CSDN,以共同進步。

相關推薦

websocket基礎websocket使用示例學習資料

介紹 Web Sockets的目標是在一個單獨的持久連線上提供全雙工、雙向通訊。在JavaScript中建立了Web Socket之後,會有一個HTTP請求傳送到瀏覽器以發起連線。在取得伺服器響應後,建立的連線會使用HTTP升級從HTTP協議交換為Web Socket協議。

0基礎怎麼學習資料,大資料學習路線學習資料

資料科學並沒有一個獨立的學科體系,統計學,機器學習,資料探勘,資料庫,分散式計算,雲端計算,資訊視覺化等技術或方法來對付資料,一起來看看資料大咖的分享。 但從狹義上來看,我認為資料科學就是解決三個問題: 1. data pre-processing;(資料預處理) 2.

二、Go學習筆記HelloWorld示例工作目錄

瞭解GOPATH目錄下的目錄結構 ,對於初學者而言只需瞭解src就行。 |- WorkSpace |- src |- pkg |- bin 本系列學習筆記部分改編自Go語言中文網,其中的教程是翻譯自國外教程,其中有一些語句翻譯不通難以理解。故

入門機器(深度)學習的書籍學習資料推薦

原理 .com 部分 nump 個人學習 概率論 並且 實驗 matplot (第一次寫博客,如有什麽地方寫得不對的,或者意見相左的,還請見諒!) 工作了一段時間,又重新回來讀書(本科計算機專業,第一個研究生是商科,現讀回了計算機專業)了,最開始想著走APP研發路線的,但是

吐血整理50G區塊鏈學習資料全免費,拿走不謝!

2018年了,你還不瞭解區塊鏈? 隨著比特幣為代表的數字貨幣的暴漲,區塊鏈迅速進入了我們的視野。 但是作為一項新興的技術,好多人想學習卻苦於沒有合適的渠道。 小編最近熬夜整理了50G關於區塊鏈的資料包,全是乾貨,從小白入門到老韭菜都需要的資料,全部無償奉獻給大家。 1、區塊鏈

nodejs環境遇到的問題學習資料

安裝nvm https://github.com/coreybutler/nvm-windows/releases 下載安裝 修改settings.txt root: D:\dev\nvm path: D:\dev\nodejs node mirror:

MyBatis概述學習資料整理

MyBatis這個名字真的是如雷貫耳,但一直沒仔細研究過,最近閒來無事,收集了些資料並寫了些Demo,算是有了個初步的認識。必須得說MyBatis的相關資料確實不算多,收集的過程也花了我不少的時間,還好框架還算易用,沒有太大的學習難度。 一、MyBatis介紹 介紹啊介紹,說說MyBatis的前世今生,這個

mongoDB基礎篇——NoSQL特性MongoDB資料查詢

 本文將進一步介紹MongoDB的特點,深入瞭解面向集合操作的資料庫增刪改查。 一、MongoDB特性 結合傳統關係型資料庫,我們從以下四個方面再度深入認識NoSQL資料庫,以MongoDB為

基礎入門黑客,附學習資料打包全送

今天心血來潮給大家寫個新手到黑客入門的路徑圖【附全部學習資料下載】! 入門介紹: 說到黑客大家可能覺得很神祕,其實我們說的的黑客是白帽子黑客,就是去尋找網站、系統、軟體等漏洞並幫助廠商修復的人,剛入門的黑客大部分從事滲透工作,而滲透大部分屬於web安全方向,就是利用漏洞來

揭祕“撩”大資料的正確姿勢生動示例解說大資料“三駕馬車”

  谷歌三駕馬車如何解決海量資料儲存與計算問題。 我是我:“緣起於美麗,相識於邂逅,廝守到白頭!”  眾聽眾:“呃,難道今天是要分享如何作詩?!” 我是我:“大家不要誤會,今天主要的分享不是如何作詩,而是《揭祕:‘撩’大資料的正確姿勢》,下面進入正題。” 話說當下技術圈的朋友,一起聚個

程式設計師必備基礎Git 命令全方位學習

## 前言 掌握Git命令是每位程式設計師必備的基礎,之前一直是用smartGit工具,直到看到大佬們都是在用Git命令操作的,回想一下,發現有些Git命令我都忘記了,於是寫了這篇博文,複習一下~ > https://github.com/whx123/JavaHome **公眾號:撿田螺的小男孩*

SQL 基礎學習 和深度學習資料

原子 rom 深度學習 允許 important href system 持久 cti SQL is a standard language for storing, manipulating and retrieving data in databasee. 關系型數據庫

小甲魚零基礎入門python第005講課後測試題答案閒聊之python的資料型別

0.在 Python 中, int 表示整型, 那你還記得 bool 、 float 和 str 分別表示什麼嗎? bool :布林型,ture代表1,false代表0;float:浮點型;str:字串 1. 你知道為什麼布林型別 (bool) 的 True 和 False 分別用 1 和 0

資料技術學習筆記之hive框架基礎1-基本架構環境部署

一、hive的介紹及其發展 "27.38.5.159" "-" "31/Aug/2015:00:04:37 +0800" "GET /course/view.php?id=27 HTTP/1.1" "303" "440" - "http://www.micro.com/user.php?act

資料技術學習筆記之Hadoop框架基礎1-Hadoop介紹偽分散式部署

一、學習建議     -》學習思想         -》設計思想:分散式             -》資料採集

資料技術學習筆記之Hadoop框架基礎2-MapReduce程式設計執行流程

一、回顧     -》hadoop的功能?         -》海量資料儲存和海量計算問題         -》分散式檔案儲存框架hdfs和

Java基礎&與&&,|與| |的聯絡與區別(詳解示例

&與&& 的聯絡與區別 一、&與&&的相同點   &與&& 都可作為 邏輯“與”的運算,即當運算子兩邊表示式結果都為True時,運算結果返回True;否則當某一表達式為False時,運算結果返回False 。

c++基礎資料型別轉換處理(二)檔案路徑擷取檔名

繼續昨天未寫完的...我是初學者,如果覺得太簡單,勿噴,如果有什麼錯誤之處,請指出,多謝~! 今天整理了寫的根據檔案路徑擷取檔名相關程式碼,主要包含替換路徑中的“/”為“'\”,然後根據“\”擷取最後的字串,即檔名 一、字串完全替換 以下方法可以替換掉

c++基礎資料型別轉換處理(一)string轉wstring檔案拷貝

使用java太長時間,已經習慣了其資料型別轉換及處理的便捷。但是,現在使用c++,不得不去面對其資料型別轉換,以及相關的處理。瞬間感覺奔潰,一天中,很多時間都交給度娘了... 檔案拷貝 本來很方便,提供了CopyFile,但是看到入參,瞬間崩潰,普通字串不行

TensorFlow遊樂場神經網路簡介,我以《Tensorflow實戰Google深度學習框架》為主,基礎最重要

轉載:https://blog.csdn.net/broadview2006/article/details/80128755 本文將通過TensorFlow遊樂場來快速介紹神經網路的主要功能。TensorFlow遊樂場(http://playground.tensorflow.org)是一個通