html5之服務器推送事件

用於服務器實時向客戶端推送消息,這個是單向推送server to clientphp

服務器端html

  header頭git

  要想服務器端推送:在服務器端的報頭要定義:
  header('Content-Type:text/event-stream'),服務器發送的響應內容應該使用這種`text/event-stream`的MIME;這樣客戶端才能理解你這是發送的不是普通的數據,   eventsource對象才能識別github

  事件流正則表達式

 

 服務器端發送事件流(內容);
 每執行一次php文件就產生一個事件流;
 事件流是由多個消息組成;
 消息是一個後面都有一個空行做爲分隔符
 一個消息就是一個事件
 一個消息能夠由一個或者多個字段組成
 字段是由字段名,冒號,字段值(數據),`字段名:值`;
 產生一個空行(即兩個換行符)表明一個事件(消息)的結束
 在一個文件中定義多個未命名事件,後面的會覆蓋前面的,
 消息中的多個字段用一個`\n`(換行符)分隔
 一個消息的結束用`\n\n`(產生一個空行);
 一個字段的開始必須是以`data:`開頭,例如`data:hello world!\n`,客戶端會接受到`hello world!`,
 編碼形式只能是使用utf-8,不能本身指定
 說的也是雲裏霧裏,其實你只要知道我要用這種特定的格式來發送數據就行,直接下面的代碼解釋json

服務器代碼數組

我就解說下面三個消息,解釋完了也就明白了,
1. 開始:報頭,這個是必須的,就是要告訴客戶端,你要把個人數據放在eventSource對象中;
2. 第一個消息:第一個字段是打印一個時間,第二個字段打印一個‘nihao’,第三個字段打印‘hehe’,第四個字段打印‘nihaoo’,第五個字段打印‘bbbb’;最後兩個\n\n表明消息的結束
注意:每一個字段後面是有一個\n,來告訴瀏覽器我這是一個字段,而兩個\n\n,是告訴瀏覽器我這個消息結束了。每一個字段的開頭必須是:data:,這個一個沒有事件名的消息
3. 第二個事件是有事件名,有名字的事件是使用event:開頭,值是事件名,這第二個消息就是定義了一個名字爲hello的事件。
4. 第三個消息:差異就是此次發送的是一個json瀏覽器

 //服務器代碼
    <?php 
    header('Content-Type:text/event-stream');
    // header("Cache-Control:no-cache");//有的瀏覽器會緩存,若是默認是緩存的話就加上這句
    date_default_timezone_set('Asia/Shanghai');
    //第一個消息
    while(1) {
        echo 'data:'.date('Y-m-d H:i:s')."\n";
        echo "data: nihao\ndata: hehe\n";
        echo "data: nihaoo\n";
        echo 'data: bbbb';
        echo "\n\n";
        //第二個消息
        echo "event: hello\n";
        echo "data: world\n\n";
        //第三個消息
        echo "event:hh\n";
        echo 'data: {"time":"aaaa"}'."\n";
        echo "\n\n";
        flush();
        sleep(1);
    }
    ?>
服務器代碼

客戶端
EventSource
這個API,要使用它,必須先實例化,而且必須給他傳遞一個參數,這個參數就是請求服務器的地址
`var ES = new EventSource('服務器地址')`;
監聽
EventSource對象屬性和方法
屬性 
 error
 message
 open
 readyState
 url緩存

方法
close()服務器

- 當鏈接發生錯誤的時候觸發error事件
- 當成功鏈接時觸發open事件
- 當接收到沒有命名的事件時觸發message事件
- readyState返回當前狀態
- 0 =>正在創建鏈接
- 1 =>鏈接處於打開狀態,正在調度事件
- 2 =>沒有創建鏈接
- url返回頁面地址
- close(),關閉鏈接
當成功鏈接後它會一直處於監聽狀態,監聽服務器發送來的信息,若是斷開了鏈接,客戶端會自動從新進行鏈接,除非你用close關閉。

命名事件
命名事件的接收要用addEventListener來監聽,用法就像我下面代碼寫的
未命名事件
用DOM0級的方法或者是DOM2級的方法都行
`ES.onmessage = function(e){}`
`ES.addEventListener('message',function(e){});`
解析
JSON
若是接收的是json,則要先解析`JSON.parse(e.data)`;
多字段
對於多個字段的,若是向要解析出來每一個字段來,就要使用正則表達式,因爲瀏覽器會把整個消息變成一個字符串,並在每一個字段後面添加一個換行符,而String類型有一個split方法,只須要用換行符做分隔,因此只須要`e.data.split(/\s/)`,這就返回一個數組,數組的每一項就是一個字讀的值

 //客戶端代碼
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>服務器推送</title>
    </head>
    <body>
    <div id="box"></div>
    <div id="box2"></div>
    <div id="box3"></div>
    <script>
        var evtSource = new EventSource('server.php');
        var box = document.getElementById("box");
        var box2 = document.getElementById('box2');
        var box3 = document.getElementById('box3');
        //
        evtSource.onerror = function(e) {
        console.log('error');
        }
        evtSource.onopen = function(e) {
            console.log("open");
        }
        evtSource.onmessage = function (e) {
            //2015-06-12 22:09:04 nihao hehe nihaoo bbbb
            box.innerHTML = e.data;
            //["2015-06-12", "22:08:55", "nihao", "hehe", "nihaoo", "bbbb"]
            console.log(e.data.split(/\s/));
            //http://127.0.0.1/server.php
            console.log(evtSource.url)
        }
        evtSource.addEventListener('hello',function(e) {
            //world
            box2.innerHTML = e.data;
        });
        evtSource.addEventListener('hh',function(evt) {
            //aaaa
            box3.innerHTML = JSON.parse(evt.data).time;
        });
    </script>
    </body>
    </html>

問題
在使用的過程當中可能會遇到php進行了緩存,這樣的會致使,客戶端數據不能及時的更新,你須要在php.ini中禁止掉緩存 `output_buffering = On`這項你禁止掉,而且在php文件中`flush()`;

好久沒有在博客園寫文章了,老是感受要寫出有點質量的文章才能拿出來,至少是本身認爲的,可是寫有點質量的文章,老是感受本身水平不行。有時想記錄學習筆記,因而我就在github上弄了一個靜態網站,這裏我會記錄個人學習和複習過程,一些小的東西我也會記錄的。地址:www.evil007.com。名字很嚇人,就是爲了霸氣了。嘿嘿。 

參考:

w3c:eventsource:http://www.w3.org/TR/eventsource/
MDN:https://developer.mozilla.org/zh-CN/docs/Server-sent_events/EventSource

相關文章
相關標籤/搜索