欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#實(shí)現(xiàn) Server-sent Events的步驟

 更新時(shí)間:2021年01月07日 16:36:04   作者:yswenli  
這篇文章主要介紹了C#實(shí)現(xiàn) Server-sent Events的步驟,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下

基于http協(xié)議交互的推送方法大概方法如下:

  1. 輪詢(ajax),比較耗費(fèi)服務(wù)器資源。COMET方式(COMET 技術(shù)并不是 HTML 5 )
  2. websocket 雙向數(shù)據(jù)推送,靈活,功能強(qiáng)大
  3. Server-sent-event(簡(jiǎn)稱SSE),單項(xiàng)數(shù)據(jù)推送(Server-sent Events 規(guī)范是 HTML 5 規(guī)范的一個(gè)組成部分)

這里我們研究一下SSE;

一、什么是SSE

Server-sent Events 規(guī)范是 HTML 5 規(guī)范的一個(gè)組成部分,具體的規(guī)范文檔見參考資源。該規(guī)范比較簡(jiǎn)單,主要由兩個(gè)部分組成:第一個(gè)部分是服務(wù)器端與瀏覽器端之間的通訊協(xié)議,第二部分則是在瀏覽器端可供 JavaScript 使用的 EventSource 對(duì)象。通訊協(xié)議是基于純文本的簡(jiǎn)單協(xié)議。服務(wù)器端的響應(yīng)的內(nèi)容類型是“text/event-stream”。響應(yīng)文本的內(nèi)容可以看成是一個(gè)事件流,由不同的事件所組成。每個(gè)事件由類型和數(shù)據(jù)兩部分組成,同時(shí)每個(gè)事件可以有一個(gè)可選的標(biāo)識(shí)符。不同事件的內(nèi)容之間通過僅包含回車符和換行符的空行(“\r\n”)來分隔。每個(gè)事件的數(shù)據(jù)可能由多行組成。嚴(yán)格地說,HTTP協(xié)議無法做到服務(wù)器主動(dòng)推送信息。但是有一種變通的發(fā)光法,就是服務(wù)器向客戶端聲明,接下來要發(fā)送的是流信息,也就是說,發(fā)送的不是一次性的數(shù)據(jù)包,而是一個(gè)數(shù)據(jù)流,會(huì)連續(xù)不斷的發(fā)送過來。這是客戶端不會(huì)關(guān)閉連接,會(huì)一直等待服務(wù)器發(fā)過來的數(shù)據(jù)流,視頻播放就是這樣的例子。本質(zhì)上這種通信就是以流信息的方式,完成一次用時(shí)很長(zhǎng)的下載。

二、SSE傳輸協(xié)議分析

了解了什么是SSE之后就發(fā)現(xiàn)這種模式針對(duì)后端開發(fā)來說是一個(gè)巨大的改進(jìn),可以像ajax一樣,卻比ajax節(jié)省資源;能實(shí)現(xiàn)websocket的服務(wù)器推送卻不需要更換協(xié)議和端口,就像寫一個(gè)特別點(diǎn)的api接口一樣方便。跟蹤一下sse的報(bào)文顯示

: this is a comment\n
reply: 3000\n
event: message\n
data: first\n\n
data: second\n\n
id: 100\n
event: myevent\n
data: third\n\n
id: 101\n
: this is a comment\n
data: fourth\n
data: fourth continue\n\n

接下就按如下來分析報(bào)文內(nèi)容:

類型為空白,表示該行是注釋,會(huì)在處理時(shí)被忽略。

類型為 data,表示該行包含的是數(shù)據(jù)。以 data 開頭的行可以出現(xiàn)多次。所有這些行都是該事件的數(shù)據(jù)。

類型為 event,表示該行用來聲明事件的類型。瀏覽器在收到數(shù)據(jù)時(shí),會(huì)產(chǎn)生對(duì)應(yīng)類型的事件。

類型為 id,表示該行用來聲明事件的標(biāo)識(shí)符。

類型為 retry,表示該行用來聲明瀏覽器在連接斷開之后進(jìn)行再次連接之前的等待時(shí)間。

三、C#實(shí)現(xiàn)SSE服務(wù)端

SSE的內(nèi)容還是很簡(jiǎn)潔的,了解了差不多了,現(xiàn)在開始做起來。

1.根據(jù)SSE規(guī)范對(duì)html的頭部進(jìn)行處理,主要就是添加text/event-stream類型,去掉緩存

 HttpContext.Current.Response.ContentType = "text/event-stream; charset=utf-8";
 HttpContext.Current.Response.SetHeader(ResponseHeaderType.CacheControl, "no-cache");
 HttpContext.Current.Response.SetHeader(ResponseHeaderType.KeepAlive, "timeout=5");
 HttpContext.Current.Response.Status = HttpStatusCode.OK;
 HttpContext.Current.Response.SendHeader(-1);

2.封裝SSE數(shù)據(jù)格式,SSE的數(shù)據(jù)都是采用UTF8進(jìn)行處理的

ServerSent(Encoding.UTF8.GetBytes($"id: {id?.Trim()}\nevent: {@event?.Trim()}\ndata: {SerializeHelper.Serialize(t)}\n\n"));

僅需二步就已經(jīng)完成了SSE服務(wù)端的處理了,下面是SAEA.MVC下面的一個(gè)完整封裝類EventStream

/****************************************************************************
*項(xiàng)目名稱:SAEA.MVC
*CLR 版本:4.0.30319.42000
*機(jī)器名稱:WALLE-PC
*命名空間:SAEA.MVC
*類 名 稱:EventStream
*版 本 號(hào):V1.0.0.0
*創(chuàng)建人: yswenli
*電子郵箱:yswenli@outlook.com
*創(chuàng)建時(shí)間:2021/1/6 14:02:09
*描述:
*=====================================================================
*修改時(shí)間:2021/1/6 14:02:09
*修 改 人: yswenli
*版 本 號(hào): V1.0.0.0
*描  述:
*****************************************************************************/
using SAEA.Common;
using SAEA.Common.Serialization;
using SAEA.Common.Threading;
using SAEA.Http.Model;
using System.Net;
using System.Text;

namespace SAEA.MVC
{
  /// <summary>
  /// SSE服務(wù)器事件流
  /// </summary>
  public class EventStream : ActionResult, IEventStream
  {
    /// <summary>
    /// 最后一次接收到的事件的標(biāo)識(shí)符
    /// </summary>
    public int LastEventID
    {
      get;
      private set;
    }

    /// <summary>
    /// SSE服務(wù)器事件流
    /// </summary>
    /// <param name="retry">指定瀏覽器重新發(fā)起連接的時(shí)間間隔</param>
    public EventStream(int retry = 3 * 1000)
    {
      this.ContentEncoding = Encoding.UTF8;

      if (HttpContext.Current.Request.Headers.ContainsKey("Last-Event-ID"))
      {
        if (int.TryParse(HttpContext.Current.Request.Headers["Last-Event-ID"], out int id))
        {
          LastEventID = id;
        }
      }

      HttpContext.Current.Response.ContentType = "text/event-stream; charset=utf-8";
      HttpContext.Current.Response.SetHeader(ResponseHeaderType.CacheControl, "no-cache");
      HttpContext.Current.Response.SetHeader(ResponseHeaderType.KeepAlive, "timeout=5");
      HttpContext.Current.Response.Status = HttpStatusCode.OK;
      HttpContext.Current.Response.SendHeader(-1);

      //心跳
      var pong = $"SAEAServer PONG {DateTimeHelper.Now:yyyy:MM:dd HH:mm:ss.fff}";

      TaskHelper.LongRunning(() =>
      {
        ServerSent(Encoding.UTF8.GetBytes($": {SerializeHelper.Serialize(pong)}\n\n"));
      }, 1000);

      //斷開重連時(shí)長(zhǎng)
      ServerSent(Encoding.UTF8.GetBytes($"retry: {retry}\n\n"));
    }
    /// <summary>
    /// 發(fā)送通知
    /// </summary>
    /// <param name="str"></param>
    /// <param name="event"></param>
    /// <param name="id"></param>
    public void ServerSent<T>(T t, string @event = "message", string id = "") where T : class
    {
      if (t != null)
        ServerSent(Encoding.UTF8.GetBytes($"id: {id?.Trim()}\nevent: {@event?.Trim()}\ndata: {SerializeHelper.Serialize(t)}\n\n"));
    }
    /// <summary>
    /// 發(fā)送通知
    /// </summary>
    /// <param name="content"></param>
    public void ServerSent(byte[] content)
    {
      HttpContext.Current.Response.SendData(content);
    }
  }
}

3.使用EventStream類快速實(shí)現(xiàn)服務(wù)器推送

將EventStream集成到Controller中,那么在業(yè)務(wù)繼承類中就可以直接使用封裝好的SSE功能了,如下例:

/****************************************************************************
*項(xiàng)目名稱:SAEA.MVCTest.Controllers
*CLR 版本:4.0.30319.42000
*機(jī)器名稱:WALLE-PC
*命名空間:SAEA.MVCTest.Controllers
*類 名 稱:EventStreamController
*版 本 號(hào):V1.0.0.0
*創(chuàng)建人: yswenli
*電子郵箱:yswenli@outlook.com
*創(chuàng)建時(shí)間:2021/1/6 13:57:09
*描述:
*=====================================================================
*修改時(shí)間:2021/1/6 13:57:09
*修 改 人: yswenli
*版 本 號(hào): V1.0.0.0
*描  述:
*****************************************************************************/
using SAEA.MVC;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace SAEA.MVCTest.Controllers
{
  /// <summary>
  /// EventStreamController
  /// </summary>
  public class EventStreamController : Controller
  {
    /// <summary>
    /// 發(fā)送通知
    /// </summary>
    /// <returns></returns>
    public ActionResult SendNotice()
    {
      try
      {
        var es = GetEventStream();

        for (int i = 0; ; i++)
        {
          var str = $"SAEA.MVC EventStream Test {i}";

          es.ServerSent(str);

          Thread.Sleep(1000);
        }
      }
      catch (Exception ex)
      {

      }
      return Empty();
    }
  }
}

四、驗(yàn)證SSE功能

了解了SSE技術(shù)相關(guān)理論,并按理論封裝了EventStream,最后使用EventStream實(shí)現(xiàn)了一個(gè)推送測(cè)試邏輯,接下來就是使用js的EventSource對(duì)象在瀏覽器中來驗(yàn)證了。

創(chuàng)建一個(gè)網(wǎng)頁,在html中的js中輸入:

     var source = new EventSource("/api/eventstream/sendnotice");
     source.onmessage = function (event) {
       document.getElementById("eventstream").innerHTML += event.data + "<br/>";
     };

 打開瀏覽器的工發(fā)者工具,在網(wǎng)絡(luò)選項(xiàng)中查看詳細(xì)內(nèi)容:

以上就是C#實(shí)現(xiàn) Server-sent Events的步驟的詳細(xì)內(nèi)容,更多關(guān)于C#實(shí)現(xiàn) Server-sent Events的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論