第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

websocket

網(wǎng)頁中的絕大多數(shù)請求使用的是 HTTP 協(xié)議,HTTP 是一個無狀態(tài)的應(yīng)用層協(xié)議,它有著即開即用的優(yōu)點,每次請求都是相互獨立的,這對于密集程度較低的網(wǎng)絡(luò)請求來說是優(yōu)點,因為無需創(chuàng)建請求的上下文條件,但是對于密集度或者實時性要求較高的網(wǎng)絡(luò)請求(例如 IM 聊天)場景來說,可能 HTTP 會力不從心,因為每創(chuàng)建一個 HTTP 請求對服務(wù)器來說都是一個很大的資源開銷。這時我們可以考慮一個相對性能較高的網(wǎng)絡(luò)協(xié)議 Socket,他的網(wǎng)頁版本被稱為 Websocket。

1. 背景

近年來,隨著 HTML5 和 w3c 的推廣開來,WebSocket 協(xié)議被提出,它實現(xiàn)了瀏覽器與服務(wù)器的實時通信,使服務(wù)端也能主動向客戶端發(fā)送數(shù)據(jù)。在 WebSocket 協(xié)議提出之前,開發(fā)人員若要實現(xiàn)這些實時性較強的功能,經(jīng)常會使用一種替代性的解決方案——輪詢。

輪詢的原理是采用定時的方式不斷的向服務(wù)端發(fā)送 HTTP 請求,頻繁地請求數(shù)據(jù)。明顯地,這種方法命中率較低,浪費服務(wù)器資源。伴隨著 WebSocket 協(xié)議的推廣,真正實現(xiàn)了 Web 的即時通信。

WebSocket 的原理是通過 JavaScript 向服務(wù)端發(fā)出建立 WebSocket 連接的請求,在 WebSocket 連接建立成功后,客戶端和服務(wù)端可以實現(xiàn)一個長連接的網(wǎng)絡(luò)管道。因為 WebSocket 本質(zhì)上是 TCP 連接,它是一個長連接,除非斷開連接否則無需重新創(chuàng)建連接,所以其開銷相對 HTTP 節(jié)省了很多。

2. API

2.1 創(chuàng)建連接

通過使用新建一個 websocket 對象的方式創(chuàng)建一個新的連接,不過在創(chuàng)建之前需要檢測一下瀏覽器是否支持 Websocket,因為只有支持 HTML5 的瀏覽器才能支持 Websocket,如下:

if(typeof window.WebSocket == 'function'){
    var ws = new WebSocket('http://127.0.0.1:8003');//創(chuàng)建基于本地的8003端口的websocket連接
}else alert("您的瀏覽器不支持websocket");

上述代碼會對本地的 8003 接口請求 Websocket 連接,前提是本地的服務(wù)器有進程監(jiān)聽 8003 端口,不然的話會連接失敗。

2.2 創(chuàng)建成功

由于 JavaScript 的各種 IO 操作是基于事件回調(diào)的,所以 Websocket 也不例外,我們需要創(chuàng)建一個連接成功的回調(diào)函數(shù)來處理連接創(chuàng)建成功之后的業(yè)務(wù)處理,如下:

ws.onopen = function(){//通過監(jiān)聽 open 時間來做創(chuàng)建成功的回調(diào)處理
    console.log('websocket連接創(chuàng)建成功')
    //進行業(yè)務(wù)處理
}

2.3 接收消息

我們辛辛苦苦創(chuàng)建了長連接就是為了發(fā)送或者接收網(wǎng)絡(luò)數(shù)據(jù),那么怎么接收呢,跟上邊提到的意義,還是需要在回調(diào)函數(shù)里處理,一不小心就陷入了回調(diào)地獄了:

ws.onmessage = function(event){
    var d = event.data;
    //接收到消息之后的業(yè)務(wù)處理
    switch(typeof d){//判斷數(shù)據(jù)的類型格式
    case "String":
        break;
    case "blob":
        break;
    case "ArrayBuffer":
        break;
    default:
        return;
    }
} 

上述實例通過監(jiān)聽 message 事件對 websocket 的消息進行一定的業(yè)務(wù)處理,這其中需要判斷數(shù)據(jù)類型格式,因為 Websocket 是基于二進制流格式的,傳輸過來的消息可能不一定是基于 utf8 的字符串格式,因此需要對格式進行判斷。

2.4 發(fā)送消息

客戶端通過使用 send 函數(shù)向服務(wù)端發(fā)送數(shù)據(jù),例如:

ws.send("一段測試消息");

可以發(fā)送文本格式,也可以發(fā)送二進制格式,例如:

var input  = document.getElementById("file"); 
input.onchange = function(){
    var file = this.files[0];
    if(!!file){
        //讀取本地文件,以gbk編碼方式輸出
        var reader = new FileReader();
        reader.readAsBinaryString(file);
        reader.onload = function(){
            //讀取完畢后發(fā)送消息
            ws.send(this.result);
        }
    }
}

2.5 監(jiān)聽錯誤信息

類似上述提到的如果創(chuàng)建實例失敗的情況,系統(tǒng)會出現(xiàn)異常,但是我們并不能準確判斷出異常的信息,這時需要通過監(jiān)聽錯誤事件來獲取報錯信息,例如:

ws.onerror = function(event){
    //這里處理錯誤信息
}

2.6 關(guān)閉連接

當服務(wù)端或者客戶端關(guān)閉 websocket 連接時,系統(tǒng)會觸發(fā)一個關(guān)閉事件,例如:

ws.onclose = function (event){
    //這里處理關(guān)閉之后的業(yè)務(wù)
}

2.7 連接的狀態(tài)

通過 websocket 對象的 readyState 屬性可以獲取到當前連接的狀態(tài),其中常用的有4種,通過 websocket 對象的幾種定義常量對比判斷:

switch (ws.readyState){
    case WebSocket.CONNECTING:break;//處于正在連接中的狀態(tài)
    case WebSocket.OPEN:break;//表示已經(jīng)連接成功
    case WebSocket.CLOSING:break;//表示連接正在關(guān)閉
    case WebSocket.CLOSE:break;//表示連接已經(jīng)關(guān)閉,或者創(chuàng)建連接失敗
    default:break;
}

3. websocket 實例

實例演示
預覽 復制
復制成功!
<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta http-equiv="content-type" content="text/html;charset=utf-8">
    <style>
        p {
            text-align: left;
            padding-left: 20px;
        }
    </style>
</head>
<body>
<div style="width: 700px;height: 500px;margin: 30px auto;text-align: center">
    <h1>聊天室實戰(zhàn)</h1>
    <div style="width: 700px;border: 1px solid gray;height: 300px;">
        <div style="width: 200px;height: 300px;float: left;text-align: left;">
            <p><span>當前在線:</span><span id="user_num">0</span></p>
            <div id="user_list" style="overflow: auto;">

            </div>
        </div>
        <div id="msg_list" style="width: 598px;border:  1px solid gray; height: 300px;overflow: scroll;float: left;">
        </div>
    </div>
    <br>
    <textarea id="msg_box" rows="6" cols="50" onkeydown="confirm(event)"></textarea><br>
    <input type="button" value="發(fā)送" onclick="send()">
</div>
</body>
</html>

<script type="text/javascript">
    var uname = window.prompt('請輸入用戶名', 'user' + uuid(8, 16));
    var ws = new WebSocket("ws://127.0.0.1:8081");
    ws.onopen = function () {
        var data = "系統(tǒng)消息:連接成功";
        listMsg(data);
    };
    ws.onmessage = function (e) {
        var msg = JSON.parse(e.data);
        var data =  msg.content;
        listMsg(data);
    };

    ws.onerror = function () {
        var data = "系統(tǒng)消息 : 出錯了,請退出重試.";
        listMsg(data);
    };

    function confirm(event) {
        var key_num = event.keyCode;
        if (13 == key_num) {
            send();
        } else {
            return false;
        }
    }

    /**
     * 發(fā)送并清空消息輸入框內(nèi)的消息
     */
    function send() {
        var msg_box = document.getElementById("msg_box");
        var content = msg_box.value;
        var reg = new RegExp("\r\n", "g");
        content = content.replace(reg, "");
        var msg = {'content': content.trim(), 'type': 'user'};
        sendMsg(msg);
        msg_box.value = '';
    }

    /**
     * 將消息內(nèi)容添加到輸出框中,并將滾動條滾動到最下方
     */
    function listMsg(data) {
        var msg_list = document.getElementById("msg_list");
        var msg = document.createElement("p");

        msg.innerHTML = data;
        msg_list.appendChild(msg);
        msg_list.scrollTop = msg_list.scrollHeight;
    }

    /**
     * 將數(shù)據(jù)轉(zhuǎn)為json并發(fā)送
     * @param msg
     */
    function sendMsg(msg) {
        var data = JSON.stringify(msg);
        ws.send(data);
    }
</script>
運行案例 點擊 "運行案例" 可查看在線運行效果

上述實例通過使用 websocket 實現(xiàn)了一個簡單的聊天室功能,功能上只實現(xiàn)了接受和發(fā)送消息的功能,在登錄認證和安全性等問題上并沒有做過多的處理,只是為了給大家連貫的展示一下 websocket 在實際項目中的使用。

4. 注意事項

實際項目中使用 websocket 需要注意一些問題 :

  • websocket 創(chuàng)建之前需要使用 HTTP 協(xié)議進行一次握手請求,服務(wù)端正確回復相應(yīng)的請求之后才能創(chuàng)建 websocket 連接;
  • 創(chuàng)建 websocket 時需要進行一些類似 token 之類的登錄認證,不然任何客戶端都可以向服務(wù)器進行 websocket 連接;
  • websocket 是明文傳輸,敏感的數(shù)據(jù)需要進行加密處理;
  • 由于 websocket 是長連接,當出現(xiàn)異常時連接會斷開,服務(wù)端的進程也會丟失,所以服務(wù)端最好有守護進程進行監(jiān)控重啟;
  • 服務(wù)器監(jiān)聽的端口最好使用非系統(tǒng)性且不常使用的端口,不然可能會導致端口沖突

5. 小結(jié)

本章介紹了 websocket 的前世今生,詳細說明其對應(yīng)的 API 的調(diào)用方式,最后使用了一個簡單的聊天室的例子來對其函數(shù)串通了一下,最后延伸了一下實際項目中使用 websocket 需要注意的地方,希望大家在實際開發(fā)中針對其優(yōu)缺點來選擇合適的使用場景。