SSE 實現服務端長連接傳數據

@zgcwkj  2024年06月22日

分類:

代碼 網站 

Server-Sent Events 協議,實現服務端長連接傳數據(流式接口)

介紹

Server-Sent Events (SSE) 是一種服務器向瀏覽器單向發送事件通知的技術,這種方法允許服務器在有新事件時實時地將更新推送到客戶端,而不需要客戶端輪詢服務器以獲取更新。SSE 是建立在 HTTP 協議之上的,因此它使用簡單的 HTTP GET 請求與服務器建立連接。

主要特征

  • 單向通信:只能由服務器向客戶端推送消息,客戶端不能通過這個連接發送消息給服務器。
  • 基於文本:SSE 傳輸的數據是基於文本的,通常是 UTF-8 編碼的。
  • 重連機制:如果連接被關閉,瀏覽器會自動尝試重新連接。
  • 事件標識:服務器可以為發送的事件指定事件類型和ID,客戶端可以根據這些信息進行相應的處理。

使用場景

  • 實時通知
  • 聊天應用
  • 股票或其它實時數據的更新

優點

  • 簡單易用,使用標准的HTTP協議。
  • 兼容性良好,大部分現代瀏覽器都支持SSE。
  • 內置自動重連機制。

缺點

  • 只支持文本數據,不可直接發送二進制數據。
  • 只能實現服務器到客戶端的單向通訊。

後端接口

  • C#
[HttpGet, AllowAnonymous]
public async IAsyncEnumerable<string> GetDataStream()
{
    var dataItems = new List<string> { "Item1", "Item2", "Item3", "Item4", "Item5" };
    foreach (var item in dataItems)
    {
        //使用迭代器返回數據項
        yield return item;
        //模擬數據生成的延時
        await Task.Delay(1000);
    }
}

[HttpGet, AllowAnonymous]
public async Task GetDataStream(CancellationToken cancellationToken)
{
    var response = Response;
    response.Headers.Add("X-Accel-Buffering", "no");//取消Nginx緩存
    response.Headers.Add("Content-Type", "text/event-stream");
    response.Headers.Add("Cache-Control", "no-cache");
    for (int i = 0; i < 10; i++)
    {
        //如果客戶端斷開連接,則退出循環
        if (cancellationToken.IsCancellationRequested) break;
        //模擬實時返回數據項
        await response.WriteAsync($"data: Message {i}\n\n");
        await response.Body.FlushAsync();
        //模擬數據生成的延時
        await Task.Delay(1000);
    }
}
  • PHP
<?php
//ini_set('display_errors', 1);
//error_reporting(E_ALL);
//設置頭部 SSE 應答
header('X-Accel-Buffering: no'); //取消Nginx緩存
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

//函數,生成SSE數據格式
function sendMsg($data) {
    echo "id: ". time() . PHP_EOL;
    echo "data: $data" . PHP_EOL.PHP_EOL;
    ob_flush();
    flush();
}

//發送數據
while (true) {
    $data = date("h:i:s", time());
    if (isset($_REQUEST["data"])) $data = $data . "_" .$_REQUEST["data"];
    //發送數據
    sendMsg($data);
    //休眠1秒
    sleep(1);
}

前端調用

  • JavaScript
if (!!window.EventSource) {
  var source = new EventSource('/GetDataStream');
  source.onmessage = function(event) {
    console.log(event.data);
  };
  source.onerror = function(error) {
    console.error("SSE 出現錯誤:", error);
  };
} else {
  console.log("瀏覽器不支持 SSE");
}


評論已關閉

Top