日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

基于ASP.NET Core api 的服务器事件发送

發(fā)布時(shí)間:2023/12/4 asp.net 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于ASP.NET Core api 的服务器事件发送 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

現(xiàn)如今程序員對(duì)Web API的調(diào)用已經(jīng)是輕車熟路。但是傳統(tǒng)的api調(diào)用都是拉模式,也就是主動(dòng)發(fā)起請(qǐng)求去調(diào)用一個(gè)api.

但是程序員往往對(duì)另一種很有用的模式很陌生,即推模式。

  • 拉模式 - 主動(dòng)調(diào)用并獲取結(jié)果的模式。

  • 推模式 - 訂閱并接受數(shù)據(jù)推送的模式。

今天要介紹的是一個(gè)被大家忽略但卻非常有用的一項(xiàng)技術(shù)。

基于HTTP/2的標(biāo)準(zhǔn)服務(wù)器事件推送模式,英文簡(jiǎn)稱Server-Sent Events,后面簡(jiǎn)稱SSE。

Server-Sent Events

這里引用MDN上的一段解釋:

EventSource 是服務(wù)器推送的一個(gè)網(wǎng)絡(luò)事件接口。一個(gè)EventSource實(shí)例會(huì)對(duì)HTTP服務(wù)開啟一個(gè)持久化的連接,以text/event-stream` 格式發(fā)送事件, 會(huì)一直保持開啟直到被要求關(guān)閉。

一旦連接開啟,來自服務(wù)端傳入的消息會(huì)以事件的形式分發(fā)至你代碼中。如果接收消息中有一個(gè)事件字段,觸發(fā)的事件與事件字段的值相同。如果沒有事件字段存在,則將觸發(fā)通用事件。

與 WebSockets,不同的是,服務(wù)端推送是單向的。數(shù)據(jù)信息被單向從服務(wù)端到客戶端分發(fā). 當(dāng)不需要以消息形式將數(shù)據(jù)從客戶端發(fā)送到服務(wù)器時(shí),這使它們成為絕佳的選擇。例如,對(duì)于處理社交媒體狀態(tài)更新,新聞提要或?qū)?shù)據(jù)傳遞到客戶端存儲(chǔ)機(jī)制(如IndexedDB或Web存儲(chǔ))之類的,EventSource無疑是一個(gè)有效方案。

以上解釋簡(jiǎn)單說明了SSE的用途,該項(xiàng)技術(shù)也是推模式的典型技術(shù)之一。同類型的技術(shù)是WebSockets, 和SignalR。

代碼是展示一項(xiàng)技術(shù)的最好辦法:

SSE客戶端實(shí)現(xiàn)

//javascript 構(gòu)造一個(gè)EventSource實(shí)例,代表一個(gè)服務(wù)器推送長(zhǎng)連接。var source = new EventSource("/api/values"); //傳入支持推送模式的api url。隨后展示。//當(dāng)普通消息被傳遞時(shí)觸發(fā)。source.onmessage = function (event) {console.log('onmessage: ' + event.data);};//當(dāng)連接打開時(shí)觸發(fā)。source.onopen = function(event) {console.log('onopen');};//當(dāng)出錯(cuò)時(shí)候觸發(fā)source.onerror = function(event) {console.log('onerror');}//使用自定義時(shí)間時(shí)候觸發(fā)。ping為自定義事件,你可以根據(jù)實(shí)際需求定義自己的事件名稱。如果事件名稱匹配,則該方法會(huì)被調(diào)用source.addEventListener("ping", function(event) {console.log('onping' + event.data);});

ASP.NET Core Api 實(shí)現(xiàn)

[HttpGet]public async Task GetValue(){//測(cè)試,debug到這里的時(shí)候你會(huì)發(fā)現(xiàn),協(xié)議使用的是HTTP/2. APS.NET Core 2.1以上就默認(rèn)支持HTTP/2,無需額外的配置。再Windows Server2016/Windows10+會(huì)自動(dòng)提供支持。string requestProtocol = HttpContext.Request.Protocol;var response = Response;//響應(yīng)頭部添加text/event-stream,這是HTTP/2協(xié)議的一部分。response.Headers.Add("Content-Type", "text/event-stream");for (int i=0;i<100;i++){// event:ping event是事件字段名,冒號(hào)后面是事件名稱,不要忘了\n換行符。await HttpContext.Response.WriteAsync($"event:ping\n");// data: 是數(shù)據(jù)字段名稱,冒號(hào)后面是數(shù)據(jù)字段內(nèi)容。注意數(shù)據(jù)內(nèi)容僅僅支持UTF-8,不支持二進(jìn)制格式。// data后面的數(shù)據(jù)當(dāng)然可以傳遞JSON String的。await HttpContext.Response.WriteAsync($"data:Controller {i} at {DateTime.Now}\r\r");// 寫入數(shù)據(jù)到響應(yīng)后不要忘記 FlushAsync(),因?yàn)樵揳pi方法是異步的,所以要全程異步,調(diào)用同步方法會(huì)報(bào)錯(cuò)。await HttpContext.Response.Body.FlushAsync();//模擬一個(gè)1秒的延遲。await Task.Delay(1000);}//數(shù)據(jù)發(fā)送完畢后關(guān)閉連接。Response.Body.Close();}

協(xié)議的字段解釋(來源MDN)

event

事件類型.如果指定了該字段,則在客戶端接收到該條消息時(shí),會(huì)在當(dāng)前的EventSource對(duì)象上觸發(fā)一個(gè)事件,事件類型就是該字段的字段值,你可以使用addEventListener()方法在當(dāng)前EventSource對(duì)象上監(jiān)聽任意類型的命名事件,如果該條消息沒有event字段,則會(huì)觸發(fā)onmessage屬性上的事件處理函數(shù).

data

消息的數(shù)據(jù)字段.如果該條消息包含多個(gè)data字段,則客戶端會(huì)用換行符把它們連接成一個(gè)字符串來作為字段值.

id

事件ID,會(huì)成為當(dāng)前EventSource對(duì)象的內(nèi)部屬性"最后一個(gè)事件ID"的屬性值.

retry

一個(gè)整數(shù)值,指定了重新連接的時(shí)間(單位為毫秒),如果該字段值不是整數(shù),則會(huì)被忽略.

消息的例子:

event: userconnect data: {"username": "bobby", "time": "02:33:48"}event: usermessage data: {"username": "bobby", "time": "02:34:11", "text": "Hi everyone."}event: userdisconnect data: {"username": "bobby", "time": "02:34:23"}event: usermessage data: {"username": "sean", "time": "02:34:36", "text": "Bye, bobby."}

這里提醒大家去仔細(xì)閱讀消息的格式。消息格式錯(cuò)誤,將導(dǎo)致數(shù)據(jù)無法正確解析。

實(shí)現(xiàn)效果

看到類型為eventsource

看到事件類型為ping,每個(gè)一秒數(shù)據(jù)被推送到客戶端一次

長(zhǎng)連接,請(qǐng)求一直未完成。

Server-Sent Events vs WebSockets

到這里大家不難發(fā)現(xiàn)SSE技術(shù)其實(shí)也是一種實(shí)時(shí)服務(wù)端推送數(shù)據(jù)的技術(shù),但是他的光環(huán)被更為閃耀的WebSockets給覆蓋了。Stackoverflow上有一篇很不錯(cuò)的對(duì)比。大家可以搜索WebSockets vs. Server-Sent events/EventSource

總的來說,SSE能實(shí)現(xiàn)的功能WebSockets都能實(shí)現(xiàn),但是SEE更輕量無需其他庫并且服務(wù)器端也非常容易編寫。同時(shí)她是基于HTTP的,自然在穿透防火墻方面也就無需太多顧慮。更多的對(duì)比結(jié)論如下(參考。

SSE 相對(duì)于 Websockets 的優(yōu)勢(shì):

  • 通過簡(jiǎn)單的 HTTP 而不是自定義協(xié)議傳輸

  • 可以使用第三方庫支持不支持SSE的瀏覽器例如IE瀏覽器。

  • 內(nèi)置支持重新連接和事件 ID

  • 更簡(jiǎn)單的協(xié)議

  • 企業(yè)防火墻進(jìn)行數(shù)據(jù)包檢查不會(huì)有問題。

Websockets 相對(duì)于 SSE 的優(yōu)勢(shì):

  • 實(shí)時(shí),雙向通信。

  • 更多瀏覽器的原生支持

SSE 的理想用例:

  • 股票行情流,數(shù)據(jù)監(jiān)控大屏數(shù)據(jù)發(fā)送,IOT物聯(lián)網(wǎng)設(shè)備數(shù)據(jù)發(fā)送。

  • 社交平臺(tái)上的狀態(tài)更新等。

  • 瀏覽器通知

SSE缺陷:

  • 不支持二進(jìn)制

  • 最大打開連接數(shù)限制。HTTP1.1 單個(gè)瀏覽器只支持6個(gè)連接(也就是打開6個(gè)Tab頁以上就會(huì)出問題,并且在Chrom和Firefox上無法解決)HTTP/2上默認(rèn)100個(gè)。

總結(jié)

SSE是一項(xiàng)輕量級(jí)的基于HTTP/2的標(biāo)準(zhǔn)協(xié)議,除了IE瀏覽器(不包含Edge)以外的其他瀏覽器均已支持該協(xié)議。后端服務(wù)ASP.NET Core 無疑也是完美支持的,.NET程序員可以放心使用。因?yàn)镾SE使用HTTP最大的優(yōu)勢(shì)可以避過防火墻的坑,WebSockets協(xié)議在穿透防火墻時(shí)候可能會(huì)有問題,而且有些老式的中間設(shè)備可能不認(rèn)識(shí)WebSockets協(xié)議導(dǎo)致兼容性問題。

SSE另一個(gè)優(yōu)點(diǎn)是無需額外的庫就可以啟用,而且支持自動(dòng)重連。非常適合從服務(wù)器推送數(shù)據(jù)到客戶端的單項(xiàng)應(yīng)用。而不用無腦的考慮WebSockets協(xié)議。甚至可以吧SSE 和 Websokets協(xié)議聯(lián)合起來使用,當(dāng)僅需服務(wù)器單項(xiàng)傳輸時(shí)候采用SSE,需要雙向傳輸時(shí)候采用Websokets.

總結(jié)

以上是生活随笔為你收集整理的基于ASP.NET Core api 的服务器事件发送的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。