雙向通訊之Comet

Comet是一種用於web的推送技術,能使服務器實時地將更新的信息傳送到客戶端,而無須客戶端發出請求,當前有三種實現方式,輪詢 長輪詢和iframe流。javascript

輪詢

客戶端和服務器之間一直進行鏈接,每隔一段時間就詢問一次html

特色: 這種方式鏈接數會不少,一個接受,一個發送。並且每次發送請求都會有Http的Header,會很耗流量,也會消耗CPU的利用率java

<body>
    <div id="clock"></div>
    <script>
        let clock = document.getElementById('clock');
        setInterval(function(){
            let xhr = new XMLHttpRequest;
            xhr.open('GET', '/clock', true);
            xhr.onreadystatechange = () => {
                if (xhr.readyState == 4 && xhr.status == 200) {
                    clock.innerHTML = xhr.responseText;
                }
            }
            xhr.send();
        }, 1000);  
    </script>
</body>
複製代碼

server.jsweb

let express = require('express');
let app = express();
app.use(express.static(__dirname));
app.get('/clock', (req,res) => {
    res.header('Access-Control-Allow-Origin', 'http://localhost:8000');
    res.end(new Date().toLocaleTimeString());
});
app.listen(8000);
複製代碼

長輪詢

在打開一條鏈接之後保持,等待服務器推送來數據再關閉的方式。express

特色: 這種方式在某種程度上減少了網絡帶寬和CPU利用率等問題。但因爲http數據包的頭部數據量每每很大(一般有400多個字節),真正被服務器須要的數據卻不多(有時只有10個字節左右),這樣的數據包在網絡上週期性的傳輸,不免對網絡帶寬是一種浪費瀏覽器

<div id="clock"></div>
    <script>
        (function poll() {
                let xhr = new XMLHttpRequest();
                xhr.open('GET', 'http://localhost:8080', true);
                xhr.onreadystatechange = function () {
                    if (xhr.readyState == 4 && xhr.status == 200) {
                        document.querySelector('#clock').innerHTML = xhr.responseText;
                        poll();
                    }
                }
                xhr.send();
        })();
    </script>
複製代碼

iframe流

在頁面中插入一個隱藏的iframe,利用其src屬性在服務器和客戶端之間建立一條長連接,服務器向iframe傳輸數據(一般是HTML,內有負責插入信息的javascript),來實時更新頁面。bash

特色: 瀏覽器兼容好服務器

<div id="clock"></div>
<iframe src="http://localhost:8000/clock" frameborder="0" />
<script>
    function setTime(ts) {
        document.querySelector("#clock").innerHTML = ts;
    }
</script>
複製代碼

server.js網絡

const express = require('express');
const app = express();
app.use(express.static(__dirname));
app.get('/clock', function (req, res) {
    res.header('Content-type', 'text/html');
    setInterval(function () {
        res.write(`<script>
        parent.setTime('${new Date().toLocalString()}'); // 若是在子窗口調用父窗口的方法,經過parent(爲window對象)
    </script>`); // 若是使用res.send()則返回數據給客戶端同時關閉鏈接
    }, 1000);
});
app.listen(8000);
複製代碼
相關文章
相關標籤/搜索