詳解Asp.net MVC SignalR來做即時Web聊天實例程式碼
本篇文章主要介紹了Asp.net SignalR來做即時Web聊天實例程式碼,具有一定的參考價值,有興趣的小夥伴們可以參考一下
本章和大家分享的內容是使用Signal R框架創建個簡易的群聊功能,主要講解如何在.Net的MVC中使用這個框架,由於這個專案有官方文件(當然全英文),後面也不打算寫分享篇了,主要目的是讓朋友們在需要使用Web即時通訊的時候有更多一種解決方案,畢竟這是微軟主推的一種解決方案之一。
SignalR網路上簡介
#ASP.NET SignalR 是為ASP.NET 開發人員提供的一個函式庫,可以簡化開發人員將即時Web 功能新增至應用程式的過程。即時 Web 功能是指這樣一種功能:當所連接的客戶端變得可用時伺服器程式碼可以立即向其推送內容,而不是讓伺服器等待客戶端請求新的資料。
SignalR當然也提供了非常簡單易用的高階API,讓伺服器端可以單一或批次呼叫客戶端上的JavaScript函數,並且非常方便地進行連接管理,例如客戶端連接到伺服器端,或斷開連接,客戶端分組,以及客戶端授權,使用SignalR都非常容易實現。
SignalR將與客戶端進行即時通訊帶給了ASP .NET 。當然這樣既好用,而且也有足夠的擴充性。以前用戶需要刷新頁面或使用Ajax輪詢才能實現的即時顯示數據,現在只要使用SignalR,就可以簡單實現了。最重要的是您無需重新建立項目,使用現有ASP .NET項目即可無縫使用SignalR。
群組聊天實例效果
咋們先來看看測試案例的效果吧,效果圖:
#介面及其簡單,樣式這裡就不考慮了,主要是展示其用法,這裡涉及到的功能有:
1. 統計在線人數量
2. 顯示線上人數的暱稱和連接方式(本測試案例支援webSockets和longPolling(長連接))
3. 群聊資訊
MVC中如何使用SignalR
首先,我們平常做法建立MVC的Web項目,然後透過Nuget控制台指令: Install-package Microsoft.AspNet.SignalR 加入SignalR的依賴,自動新增的套件如下:
<package id="Microsoft.AspNet.SignalR" version="2.2.2" targetFramework="net45" /> <package id="Microsoft.AspNet.SignalR.Core" version="2.2.2" targetFramework="net45" /> <package id="Microsoft.AspNet.SignalR.JS" version="2.2.2" targetFramework="net45" /> <package id="Microsoft.AspNet.SignalR.SystemWeb" version="2.2.2" targetFramework="net45" />
並且自動往MVC專案中的Script資料夾中增加相關的js檔案:
jquery.signalR-2.2. 2.min.js
jquery.signalR-2.2.2.js
然後,我們需要在專案一級目錄建立一個檔案名稱為Startup.cs的類,裡面主要內容補全不下:
[assembly: OwinStartup(typeof(Stage.Api.Extend.Startup))] namespace Stage.Api.Extend { public class Startup { public void Configuration(IAppBuilder app) { app.MapSignalR("/chat", new Microsoft.AspNet.SignalR.HubConfiguration { EnableDetailedErrors = true, EnableJavaScriptProxies = true }); } } }
首先我們從上往下分析注意點:
#1. OwinStartup(Type)
建構子傳遞的是一個類型,而這個類型對應的就是我們所建立的Startup類,這個透過這個建構函式類別標記起始位置;
2. namespace Stage.Api.Extend
是我專案的命名空間,這個可以隨便定義;
3. public void Configuration(IAppBuilder app)
函數是固定必須的,這裡程式會先進入這個方法執行裡面的邏輯程式碼;
4. app.MapSignalR
是擴充的IAppBuilder介面方法,他有多種表現形式,這裡我選擇的是public <a href="http://www.php.cn/wiki/188.html" target="_blank">static</a> IAppBuilder MapSignalR(this IAppBuilder builder, <a href="http://www.php.cn/wiki/57.html" target="_blank">string</a> path, HubConfiguration configuration);
,這裡看有點類似咋們MVC的路由,這裡主要注意的是這個Path參數,在前端頁面的時候需要用到這個路徑;
到这里后台需要的配置其实已经就完成了,下面是具体需要操作的业务逻辑处理类,新建一个类(这里我取名为ChatHub)并继承Hub(这是SignalR框架提供),然后里面的逻辑代码如下:
public class ChatHub : Hub { // public int Num = 10001; public static List<MoHubUser> _Users = new List<MoHubUser>(); /// <summary> /// 添加聊天人 /// </summary> /// <param name="user"></param> public void AddUser(MoHubUser user) { user.Id = Context.ConnectionId; if (!_Users.Any(b => b.Id == user.Id)) { _Users.Add(user); } //Clients.All.newUser(user); Clients.All.userList(_Users); } /// <summary> /// 发送信息 /// </summary> /// <param name="user"></param> /// <param name="message"></param> public void SendAll(MoHubUser user, string message) { Clients.All.addNewMessageToPage(user, message); } /// <summary> /// 某个聊天人退出是,通知所有在线人重新加载聊天人数 /// </summary> /// <param name="stopCalled"></param> /// <returns></returns> public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled) { var user = _Users.SingleOrDefault(x => x.Id == Context.ConnectionId); if (user != null) { _Users.Remove(user); Clients.All.userList(_Users); } return base.OnDisconnected(stopCalled); } }
上面的3个方法分别做了:添加聊天人到List,发送信息到客户端,某个连接失效后通知各个有效的聊天人重新加载信息;这里值得关注的是通过重新 public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled)
方法来实现捕获并移除失效连接(这里是聊天人的信息);整篇测试用例通过Context.ConnectionId来保证连接的唯一性,只要有新的链接请求,那么服务端就会分配一个唯一串给这个链接,当客户端关闭页面或关闭链接这个是有就能在OnDisconnected方法中捕获到这个失效的链接的ConnectionId,这样就达到了移除失效聊天人的要求了;为了代码的方便性,这里创建了一个聊天人信息类:
public class MoHubUser { public string Id { get; set; } public string NickName { get; set; } public string TransportMethod { get; set; } }
到这里后台的聊天室代码就完成了就是这么简单;我们再来看试图中如何来写代码,这里我先给出我的html布局代码:
@{ ViewBag.Title = "神牛聊天室 - SignalR"; } <style type="text/css"> .p_left { width: 70%; float: left; } .p_right { width: 28%; float: left; } .ul { list-style: none; border: 1px solid #ccc; height: 500px; overflow-y: scroll; color: black; } .ul li { padding-top: 5px; padding-right: 25px; } .ul_user { list-style: none; } .ul_user li { padding-top: 5px; } .send { position: relative; background: #eae7e7; border-radius: 5px; /* 圆角 */ padding-top: 4px; padding-left: 5px; margin-top: 13px; } .send .arrow { position: absolute; top: -16px; font-size: 0; border: solid 8px; border-color: #fff #fff #eae7e7 #fff; } </style> <h3>@ViewBag.Title 在线人数:<span id="sapnUserTotal">0</span>人</h3> <p class="container text-left"> <p class="p_left"> <ul class="ul" id="discussion"></ul> <textarea rows="5" class="form-control" id="message" maxlength="500" placeholder="开始聊天. . ." style="max-width: 100%"></textarea><br /> <input type="button" id="sendmessage" value="发 送" class="btn btn-default" /> <input type="hidden" id="displayname" /> </p> <p class="p_right"> <ul id="users" class="ul_user"></ul> </p> </p> <script src="~/Scripts/jquery.signalR-2.2.2.min.js"></script> @*<script src="~/chat/hubs"></script>*@
客户端这里写法大致有两种选择,一种直接使用生成的代理来操作,一种不用自动生成的代理采用手动创建代理的方式;为了内容的简洁性,这里只简单讲解下自动生成的代理方式,而更多的是分享手动创建代理链接的方式;
使用生成的代理获取链接
首先,我们需要通过Script标签来引用一下自动生成代理的路径: <script src="~/chat/hubs"></script>
,注意啦这里的路径/chat对应的就是咋们在前面Startup.cs文件中配置 app.MapSignalR("/chat"
路径,而后面/hubs固定的写法(至少目前我还没更多的试验过),只有先应用了这个~/chat/hubs,才能在后面使用生成的代理,先上段代码:
var chat = $.connection.chatHub; chat.client.newUser = function (user) { $("#users").append(' <li><strong>' + user.NickName + '[' + user.TransportMethod + ']</strong></li>'); }; chat.client.userList = function (users) { console.log(users); $("#sapnUserTotal").html(users.length); $.each(users, function (i, item) { $("#users").append(' <li>[' + item.TransportMethod + '] <strong>' + item.NickName + '</strong>(' + item.Id + ')</li>'); }); }; chat.client.addNewMessageToPage = function (user, message) { console.log(user); $("#discussion").append(' <li ><span><strong>' + user.NickName + '[' + user.TransportMethod + ']</strong>:</span><p class="send">' + message + '<p class="arrow"></p></p></li>'); }; //connection.hub.start({ transport: ['webSockets', 'longPolling'] }).done(function () { // my.TransportMethod = connection.hub.transport.name; // chat.server.addUser(my); // $('#sendmessage').click(function () { // //console.log(chat); // var content = $.trim($('#message').val()); // if (content.length <= 0) { $('#message').val('').focus(); return; } // chat.server.sendAll(my, content); // $('#message').val('').focus(); // }); //}).fail(function () { // alert("链接聊天室失败,请重新刷新页面。"); //});
咋们逐步来解析下代码注意点:
1. var chat = $.connection.chatHub;
这里的chatHub对应的就是咋们创建的并继承Hub的ChatHub类,由于js变量开头都是小写,所以这里是chatHub,这句活就表示链接到咋们后端了ChatHub类了,然后就可以使用里面的方法啦(这种有点类似于早期的webform中某种ajax请求的写法)
2. 通过chat.client.xxx来接收服务端通知的消息,而这个xxx对应的方法名称和咋们后端的Clients.All.xxx,本章实例对应的是:chat.client.userList = function (users){}对应Clients.All.userList(_Users);这样后端就能直接通知客户端的对应方法了;注意这里我后端Clients.All用的是通知全部客户端的意思,如果您需要通知指定的链接需要用到的是: T Client(string connectionId);
方法
3. chat.client是后端调用客户端,那相对的chat.server就是客户端请求服务端,和上面一样通过chat.server.xxx来指定请求的服务端方法,注意这个时候服务端方法指的是继承类Hub的子类的公共方法(本篇对应的是:chat.server.sendAll(my, content)对应ChatHub.cs文件中的 public void SendAll(MoHubUser user, string message)
函数)
4. connection.hub.start({ transport: ['webSockets', 'longPolling'] })
来指定运行的交互协议
以上就是使用生成代理的方式,按照上面的注意点来写应该不是问题;
使用手动创建反向代理来链接
不采用生成的代码的方式,我们只需要修改前端就行了,后台代码不用变或设置不用变动;首先我们把上面说的Script引用自动代理的代码去掉,因为这个时候不需要了,我们还是先上代码:
var my = { NickName: "神牛001", TransportMethod: "" }; var connection = $.hubConnection("/chat/hubs"); var chat = connection.createHubProxy('chatHub'); chat.on("userList", function (users) { console.log(users); $("#sapnUserTotal").html(users.length); $("#users").html(""); $.each(users, function (i, item) { $("#users").append(' <li>[' + item.TransportMethod + '] <strong>' + item.NickName + '</strong>(' + item.Id + ')</li>'); }); }); chat.on("addNewMessageToPage", function (user, message) { console.log(user); $("#discussion").append(' <li ><span><strong>' + user.NickName + '[' + user.TransportMethod + ']</strong>:</span><p class="send">' + message + '<p class="arrow"></p></p></li>'); var p = document.getElementById('discussion'); //p.scrollTop = p.scrollHeight; p.scrollTop = 999999; }); var nickName = prompt("请输入一个昵称:", my.NickName); my.NickName = nickName.length > 0 ? nickName : my.NickName; $('#displayname').val(nickName); $('#message').focus(); connection.start({ transport: ['webSockets', 'longPolling'] }).done(function () { my.TransportMethod = connection.transport.name; //console.log(my.TransportMethod); chat.invoke("addUser", my); $('#sendmessage').click(function () { var content = $.trim($('#message').val()); if (content.length <= 0) { $('#message').val('').focus(); return; } chat.invoke("sendAll", my, content); $('#message').val('').focus(); }); });
同样列出如下注意点:
1. var connection = $.hubConnection("/chat/hubs");
创建链接,这里的path同样对应后端的 app.MapSignalR("/chat" ,路径保持一致
2. var chat = connection.createHubProxy('chatHub');
来创建反向代理链接,这里的name:chatHub对应的是后端的ChatHub类名称
3. 通过on("xxx",function(){})函数来绑定服务端通知客户端的事件,xxx对应Clients.All.xxx中的xxx
4. connection.start({ transport: ['webSockets', 'longPolling'] })
來設定允許的連結方式,並開始連結
#5. connection.transport .name來取得連結的方式名稱,預設start不設定的話有這麼多種:webSockets,foreverFrame,serverSentEvents,longPolling
6. chat.invoke("xxx", param1, param2)透過invoke來映射繼承類別Hub的類別的公共方法,這裡實例對應的是: chat.invoke("sendAll", my, content)
對應public void SendAll(MoHubUser user, string message)
以上是詳解Asp.net MVC SignalR來做即時Web聊天實例程式碼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

一、日誌輸出到檔案使用模組:logging可以產生自訂等級日誌,可以輸出日誌到指定路徑日誌等級:debug(偵錯日誌)=5){clearTimeout(time)//如果連續10次取得的都是空日誌清除定時任務}return}if(data.log_type==2){//如果取得到新日誌for(i=0;i

Caddy簡介Caddy是一款功能強大,擴展性高的Web伺服器,目前在Github上已有38K+Star。 Caddy採用Go語言編寫,可用於靜態資源託管和反向代理。 Caddy具有以下主要特性:比較Nginx複雜的配置,其獨創的Caddyfile配置非常簡單;可以透過其提供的AdminAPI實現動態修改配置;預設支援自動化HTTPS配置,能自動申請HTTPS憑證並進行配置;能夠擴展到數以萬計的站點;可以在任意地方執行,沒有額外的依賴;採用Go語言編寫,內存安全更有保證。安裝首先我們直接在CentO

JavaAPI開發中使用Jetty7進行Web伺服器處理隨著互聯網的發展,Web伺服器已經成為了應用程式開發的核心部分,同時也是許多企業所關注的焦點。為了滿足日益增長的業務需求,許多開發人員選擇使用Jetty進行Web伺服器開發,其靈活性和可擴展性受到了廣泛的認可。本文將介紹如何在JavaAPI開發中使用Jetty7進行We

防擋臉彈幕,即大量彈幕飄過,但不會遮擋視訊畫面中的人物,看起來像是從人物背後飄過去的。機器學習已經火了好幾年了,但很多人都不知道瀏覽器中也能運行這些能力;本文介紹在視頻彈幕方面的實踐優化過程,文末列舉了一些本方案可適用的場景,期望能開啟一些腦洞。 mediapipeDemo(https://google.github.io/mediapipe/)展示主流防擋臉彈幕實現原理點播up上傳視訊伺服器後台計算提取視訊畫面中的人像區域,轉換成svg儲存用戶端播放視訊的同時,從伺服器下載svg與彈幕合成,人像

表單驗證是Web應用程式開發中非常重要的環節,它能夠在提交表單資料之前對資料進行有效性檢查,避免應用程式出現安全漏洞和資料錯誤。使用Golang可以輕鬆實現網頁應用程式的表單驗證,本文將介紹如何使用Golang來實作網頁應用程式的表單驗證。一、表單驗證的基本要素在介紹如何實作表單驗證之前,我們需要知道表單驗證的基本要素是什麼。表單元素:表單元素是指

首先你會有個疑惑,frp是什麼呢?簡單的說frp就是內網穿透工具,配置客戶端以後,可以透過伺服器來存取內部網路。現在我的伺服器,已經用nginx做站了,80端口只有一個,那如果frp的服務端也想使用80端口,那該怎麼辦呢?經過查詢,這個是可以實現的,就是利用nginx的反向代理來實現。補充一下:frps就是伺服器端(server),frpc就是客戶端(client)。第一步:修改伺服器中nginx.conf設定檔在nginx.conf中http{}裡加入以下參數,server{listen80

Cockpit是一個面向Linux伺服器的基於Web的圖形介面。它主要是為了使新用戶/專家用戶更容易管理Linux伺服器。在本文中,我們將討論Cockpit存取模式以及如何從CockpitWebUI切換Cockpit的管理存取。內容主題:駕駛艙進入模式查找當前駕駛艙訪問模式從CockpitWebUI啟用Cockpit的管理訪問從CockpitWebUI禁用Cockpit的管理訪問結論駕駛艙進入模式駕駛艙有兩種訪問模式:受限訪問:這是駕駛艙的默認訪問模式。在這種存取模式下,您無法從駕駛艙Web用戶

Web標準是一組由W3C和其他相關組織制定的規範和指南,它包括HTML、CSS、JavaScript、DOM、Web可訪問性和性能優化等方面的標準化,透過遵循這些標準,可以提高頁面的兼容性、可訪問性、可維護性和效能。 Web標準的目標是使Web內容能夠在不同的平台、瀏覽器和裝置上一致地展示和交互,提供更好的使用者體驗和開發效率。
