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

Asp.net SignalR應(yīng)用并實(shí)現(xiàn)群聊功能

 更新時(shí)間:2017年04月06日 11:22:51   作者:lining.name  
這篇文章主要為大家分享了Asp.net SignalR應(yīng)用并實(shí)現(xiàn)群聊功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

ASP.NET SignalR 是為 ASP.NET 開(kāi)發(fā)人員提供的一個(gè)庫(kù),可以簡(jiǎn)化開(kāi)發(fā)人員將實(shí)時(shí) Web 功能添加到應(yīng)用程序的過(guò)程。實(shí)時(shí) Web 功能是指這樣一種功能:當(dāng)所連接的客戶端變得可用時(shí)服務(wù)器代碼可以立即向其推送內(nèi)容,而不是讓服務(wù)器等待客戶端請(qǐng)求新的數(shù)據(jù)。(來(lái)自官方介紹。)

SignalR官網(wǎng)

 -1、寫這篇的原因

在上篇文章B/S(Web)實(shí)時(shí)通訊解決方案中,并沒(méi)有詳情介紹SignalR,所以另起一篇專門介紹SignalR,本文的側(cè)重點(diǎn)是Hub功能。 

0、先看最終實(shí)現(xiàn)效果

github:https://github.com/Emrys5/SignalRGroupChatDemo

在線演示:http://chat.lining.name/

 1、準(zhǔn)備工作

1.1、在NuGet上首先下載SignalR的包。

1.2、配置Owin與SignalR

1.2.1、新建Startup類,注冊(cè)SignalR

public class Startup
 {
 public void Configuration(IAppBuilder app)
 {
  app.MapSignalR();
 }
 }

然后在web.config配置Startup類,在configuration=>appSettings節(jié)點(diǎn)中添加

<add key="owin:AppStartup" value="SignalRChat.App_Start.Startup"/>

1.2.2、在頁(yè)面引入SignalR的js

1、由于SignalR前端是基于jQuery的,所以頁(yè)面需引入jQuery。

2、引入SignalR的js 。

3、引入最重要的hubs js,這個(gè)js其實(shí)并不存在,SignalR會(huì)反射獲取所有供客戶端調(diào)用的方法放入hubs js中。

<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery.signalR-2.2.1.min.js"></script> 
<script src="~/signalr/hubs"></script>

1.2.3、新建GroupChatHub類,并繼承Hub抽象類

在hub類中的方法就是提供給客戶端調(diào)用的js方法。

在js中就可以用signalr調(diào)用SendMsg。

[HubName("simpleHub")]
 public class SimpleHub : Hub
 { 
 public void SendMsg(string msg)
 {
  
 }

 }

這樣基本上前期準(zhǔn)備工作就做完了,后面就是具體的操作。

2、原理與簡(jiǎn)單的編程

其實(shí)原理如果簡(jiǎn)單點(diǎn)理解就很簡(jiǎn)單,因?yàn)閔ttp是無(wú)狀態(tài)的,所以每次請(qǐng)求以后都會(huì)與服務(wù)器斷開(kāi)鏈接,那就是說(shuō)客戶端可以很容易找到服務(wù)器,但是服務(wù)器如果想給你客戶端發(fā)送消息就比較麻煩,如果不明白的可以參考上一篇文章B/S(Web)實(shí)時(shí)通訊解決方案。

SignalR就很好的解決了這個(gè)問(wèn)題,也就說(shuō)實(shí)現(xiàn)了實(shí)現(xiàn)了瀏覽器與服務(wù)器的全雙工通信。

2.1、客戶端至服務(wù)端(B=>S)

客戶端代碼

<script type="text/javascript"> 
 var ticker = $.connection.simpleHub;
 $.connection.hub.start();

 $("#btn").click(function () {

 // 鏈接完成以后,可以發(fā)送消息至服務(wù)端
 ticker.server.sendMsg("需要發(fā)送的消息");
 });
 
</script>

服務(wù)端代碼

[HubName("simpleHub")]
 public class SimpleHub : Hub
 {
 public void SendMsg(string msg)
 {
  // 獲取鏈接id
  var connectionId = Context.ConnectionId; 
  // 獲取cookie
  var cookie = Context.RequestCookies;

 }

 }

其中SimpleHub就是我們定義的繼承Hub類SimpleHub,然后我們可以用特性HubName進(jìn)行重命名。

然后開(kāi)始鏈接。

在鏈接完成以后,我們就可以調(diào)用在SimpleHub類中調(diào)用的方法。這就就很簡(jiǎn)單的實(shí)現(xiàn)了客戶端至服務(wù)端發(fā)送消息。

我們還可以在Context中獲取我們想要的東西,比如鏈接id,cookie等。

2.2、服務(wù)端至客戶端(S=>B)

服務(wù)端代碼

[HubName("simpleHub")]
 public class SimpleHub : Hub
 {
 public void SendMsg(string msg)
 {
  Clients.All.msg("發(fā)送給客戶端的消息"); 
 }

 }

客戶端代碼

<script type="text/javascript">

 var ticker = $.connection.groupChatHub;
 $.connection.hub.start();

 ticker.client.msg = function (data) {
 console.log(data);
 } 
</script>

這里演示了怎么發(fā)送消息至客戶端,也是SignalR比較重要的功能,這里有兩個(gè)問(wèn)題需要解決。

問(wèn)題一、這里是發(fā)送消息給所有連著的客戶端,如果是單個(gè)客戶端或者是一批客戶端應(yīng)該怎么發(fā)送。

問(wèn)題二、我們?cè)谡{(diào)用msg給個(gè)客戶端發(fā)送消息時(shí)是在接收消息以后做的反饋,然后發(fā)送消息給客戶端,這樣就很類似ajax了,服務(wù)端并沒(méi)有主動(dòng)給客戶端發(fā)送消息。

解決:

問(wèn)題一、Clients可以給特性的一群或者一個(gè)客戶端發(fā)送消息

// 所有人
Clients.All.msg("發(fā)送給客戶端的消息"); 
// 特定 cooectionId
Clients.Client("connectionId").msg("發(fā)送給客戶端的消息");
// 特定 group
Clients.Group("groupName").msg("發(fā)送給客戶端的消息");

這是比較常用的三個(gè),當(dāng)然還有很多,比如AllExcept,Clients。

在SignalR2.0中還添加了Others,OthersInGroup,OthersInGroups等等。

問(wèn)題二、我們可以在需要發(fā)送消息的地方調(diào)用GlobalHost.ConnectionManager.GetHubContext<SimpleHub>().Clients中獲取Clients。獲取Clients并發(fā)送消息我們最好寫成單例模式,因?yàn)檫@種需求很符合單例,群聊中有詳細(xì)的代碼。

3、SignalR實(shí)現(xiàn)群聊

以上的介紹和代碼已經(jīng)可以實(shí)現(xiàn)b=>s和s=>b了,那實(shí)現(xiàn)群聊和單獨(dú)聊天就比較簡(jiǎn)單了。

由于功能比較簡(jiǎn)單,所有我把用戶名存到了cookie里,也就說(shuō)第一次進(jìn)來(lái)時(shí)需要設(shè)置cookie。

還有就是在hub中要實(shí)現(xiàn)OnConnected、OnDisconnected和OnReconnected,然后在方法中設(shè)置用戶和connectionid和統(tǒng)計(jì)在線用戶,以便聊天使用。

hub代碼

/// <summary>
 /// SignalR Hub 群聊類
 /// </summary>
 [HubName("groupChatHub")] // 標(biāo)記名稱供js調(diào)用
 public class GroupChatHub : Hub
 {
 /// <summary>
 /// 用戶名
 /// </summary>
 private string UserName
 {
  get
  {
  var userName = Context.RequestCookies["USERNAME"];
  return userName == null ? "" : HttpUtility.UrlDecode(userName.Value);
  }
 }

 /// <summary>
 /// 在線用戶
 /// </summary>
 private static Dictionary<string, int> _onlineUser = new Dictionary<string, int>();

 /// <summary>
 /// 開(kāi)始連接
 /// </summary>
 /// <returns></returns>
 public override Task OnConnected()
 {
  Connected();
  return base.OnConnected();
 }


 /// <summary>
 /// 重新鏈接
 /// </summary>
 /// <returns></returns>
 public override Task OnReconnected()
 {
  Connected();
  return base.OnReconnected();
 }


 private void Connected()
 {
  // 處理在線人員
  if (!_onlineUser.ContainsKey(UserName)) // 如果名稱不存在,則是新用戶
  {

  // 加入在線人員
  _onlineUser.Add(UserName, 1);

  // 向客戶端發(fā)送在線人員
  Clients.All.publshUser(_onlineUser.Select(i => i.Key));

  // 向客戶端發(fā)送加入聊天消息
  Clients.All.publshMsg(FormatMsg("系統(tǒng)消息", UserName + "加入聊天"));
  }
  else
  {
  // 如果是已經(jīng)存在的用戶,則把在線鏈接的個(gè)數(shù)+1
  _onlineUser[UserName] = _onlineUser[UserName] + 1;
  }

  // 加入Hub Group,為了發(fā)送單獨(dú)消息
  Groups.Add(Context.ConnectionId, "GROUP-" + UserName);
 }


 /// <summary>
 /// 結(jié)束連接
 /// </summary>
 /// <param name="stopCalled"></param>
 /// <returns></returns>
 public override Task OnDisconnected(bool stopCalled)
 {
  // 人員鏈接數(shù)-1
  _onlineUser[UserName] = _onlineUser[UserName] - 1;

  // 判斷是否斷開(kāi)了所有的鏈接
  if (_onlineUser[UserName] == 0)
  {
  // 移除在線人員
  _onlineUser.Remove(UserName);

  // 向客戶端發(fā)送在線人員
  Clients.All.publshUser(_onlineUser.Select(i => i.Key));

  // 向客戶端發(fā)送退出聊天消息
  Clients.All.publshMsg(FormatMsg("系統(tǒng)消息", UserName + "退出聊天"));
  }

  // 移除Hub Group
  Groups.Remove(Context.ConnectionId, "GROUP-" + UserName);
  return base.OnDisconnected(stopCalled);
 }

 /// <summary>
 /// 發(fā)送消息,供客戶端調(diào)用
 /// </summary>
 /// <param name="user">用戶名,如果為0,則是發(fā)送給所有人</param>
 /// <param name="msg">消息</param>
 public void SendMsg(string user, string msg)
 {
  if (user == "0")
  {
  // 發(fā)送給所有用戶消息
  Clients.All.publshMsg(FormatMsg(UserName, msg));
  }
  else
  {
  //// 發(fā)送給自己消息
  //Clients.Group("GROUP-" + UserName).publshMsg(FormatMsg(UserName, msg));

  //// 發(fā)送給選擇的人員
  //Clients.Group("GROUP-" + user).publshMsg(FormatMsg(UserName, msg));


  // 發(fā)送給自己消息
  Clients.Groups(new List<string> { "GROUP-" + UserName, "GROUP-" + user }).publshMsg(FormatMsg(UserName, msg));

  }
 }


 /// <summary>
 /// 格式化發(fā)送的消息
 /// </summary>
 /// <param name="name"></param>
 /// <param name="msg"></param>
 /// <returns></returns>
 private dynamic FormatMsg(string name, string msg)
 {
  return new { Name = name, Msg = HttpUtility.HtmlEncode(msg), Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") };
 }
 }

js代碼

<script type="text/javascript">
 $(function () {

  // 鏈接hub
  var ticker = $.connection.groupChatHub;
  $.connection.hub.start();

  // 接收服務(wù)端發(fā)送的消息
  $.extend(ticker.client, {

  // 接收聊天消息
  publshMsg: function (data) {
   $("#msg").append("<li><span class='p'>" + data.Name + ":</span>" + data.Msg + " <span class='time'>" + data.Time + "</span></li>")
   $("#msg").parents("div")[0].scrollTop = $("#msg").parents("div")[0].scrollHeight;
  },

  // 接收在線人員,然后加入Select,以供單獨(dú)聊天選中
  publshUser: function (data) {
   $("#count").text(data.length);
   $("#users").empty();
   $("#users").append('<option value="0">所有人</option>');
   for (var i = 0; i < data.length; i++) {
   $("#users").append('<option value="' + data[i] + '">' + data[i] + '</option>')
   }

  }
  });

  // 發(fā)送消息按鈕
  $("#btn-send").click(function () {
  var msg = $("#txt-msg").val();
  if (!msg) {
   alert('請(qǐng)輸入內(nèi)容!'); return false;
  }
  $("#txt-msg").val('');

  // 主動(dòng)發(fā)送消息,傳入發(fā)送給誰(shuí),和發(fā)送的內(nèi)容。
  ticker.server.sendMsg($("#users").val(), msg);
  });

 });
 </script>

html代碼

<h2>
 群聊系統(tǒng)(<span id="count">1</span>人在線):@ViewBag.UserName
</h2>


<div style="overflow:auto;height:300px">
 <ul id="msg"></ul>
</div>

<select id="users" class="form-control" style="max-width:150px;">
 <option value="0">所有人</option>
</select>

<input type="text" onkeydown='if (event.keyCode == 13) { $("#btn-send").click() }' class="form-control" id="txt-msg" placeholder="內(nèi)容" style="max-width:400px;" />
<br />
<button type="button" id="btn-send">發(fā)送</button>

這樣就消息了群聊和發(fā)送給特定的人聊天功能。

3.1、封裝主動(dòng)發(fā)送消息的單例

/// <summary>
 /// 主動(dòng)發(fā)送給用戶消息,單例模式
 /// </summary>
 public class GroupChat
 {
 /// <summary>
 /// Clients,用來(lái)主動(dòng)發(fā)送消息
 /// </summary>
 private IHubConnectionContext<dynamic> Clients { get; set; }

 private readonly static GroupChat _instance = new GroupChat(GlobalHost.ConnectionManager.GetHubContext<GroupChatHub>().Clients);

 private GroupChat(IHubConnectionContext<dynamic> clients)
 {
  Clients = clients;
 }

 public static GroupChat Instance
 {
  get
  {
  return _instance;
  }
 }


 /// <summary>
 /// 主動(dòng)給所有人發(fā)送消息,系統(tǒng)直接調(diào)用
 /// </summary>
 /// <param name="msg"></param>
 public void SendSystemMsg(string msg)
 {
  Clients.All.publshMsg(new { Name = "系統(tǒng)消息", Msg = msg, Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") });
 }
 }

如果需要發(fā)送消息,直接調(diào)用SendSystemMsg即可。

GroupChat.Instance.SendSystemMsg("消息");

 4、結(jié)語(yǔ)

啥也不說(shuō)了直接源碼

github:https://github.com/Emrys5/SignalRGroupChatDemo

在線演示:http://chat.lining.name/

最后望對(duì)各位有所幫助,本文原創(chuàng),歡迎拍磚和推薦。 

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • C#.net格式化時(shí)間字符串達(dá)到不同的顯示效果

    C#.net格式化時(shí)間字符串達(dá)到不同的顯示效果

    時(shí)候我們要對(duì)時(shí)間進(jìn)行轉(zhuǎn)換,達(dá)到不同的顯示效果,本文將幫助你實(shí)現(xiàn)這個(gè)多彩的效果,整理很詳細(xì),以備不時(shí)之需,感興趣的朋友可以了解下,或許本文對(duì)你有所幫助
    2013-01-01
  • ASP.NET?Core?MVC自定義Tag?Helpers用法介紹

    ASP.NET?Core?MVC自定義Tag?Helpers用法介紹

    這篇文章介紹了ASP.NET?Core?MVC自定義Tag?Helpers的用法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-02-02
  • .Net項(xiàng)目在Docker容器中開(kāi)發(fā)部署

    .Net項(xiàng)目在Docker容器中開(kāi)發(fā)部署

    這篇文章介紹了.Net項(xiàng)目在Docker容器中開(kāi)發(fā)部署的方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • asp.net實(shí)現(xiàn)文件下載的代碼

    asp.net實(shí)現(xiàn)文件下載的代碼

    asp.net中也需要實(shí)現(xiàn)文件的下載,因此下面的方法可以參考下除了第四種不推薦以外,其他的都可以,但是個(gè)人感覺(jué)分塊下載的要好一點(diǎn)。沒(méi)有仔細(xì)測(cè)試,所以可能有問(wèn)題。
    2011-02-02
  • ASP.NET URL偽靜態(tài)重寫實(shí)現(xiàn)方法

    ASP.NET URL偽靜態(tài)重寫實(shí)現(xiàn)方法

    ASP.NET下為靜態(tài)的實(shí)現(xiàn)方法。
    2009-12-12
  • asp.net SharpZipLib的壓縮與解壓?jiǎn)栴}

    asp.net SharpZipLib的壓縮與解壓?jiǎn)栴}

    關(guān)于SharpZipLib的壓縮與解壓縮的實(shí)現(xiàn)代碼,網(wǎng)絡(luò)上有一堆,千遍一律,連注釋也一模一樣,一模一樣的文章拷來(lái)拷去??
    2009-11-11
  • ASP.NET MVC實(shí)現(xiàn)圖片上傳、圖片預(yù)覽顯示

    ASP.NET MVC實(shí)現(xiàn)圖片上傳、圖片預(yù)覽顯示

    這篇文章主要為大家詳細(xì)介紹了ASP.NET MVC實(shí)現(xiàn)圖片上傳、圖片預(yù)覽顯示的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-05-05
  • 詳解ASP.NET MVC Form表單驗(yàn)證

    詳解ASP.NET MVC Form表單驗(yàn)證

    這篇文章主要為大家詳細(xì)介紹了ASP.NET MVC Form表單驗(yàn)證,一般驗(yàn)證方式有Windows驗(yàn)證和表單驗(yàn)證,web項(xiàng)目用得更多的是表單驗(yàn)證,感興趣的小伙伴們可以參考一下
    2016-03-03
  • asp.net DataTable相關(guān)操作集錦(篩選,取前N條數(shù)據(jù),去重復(fù)行,獲取指定列數(shù)據(jù)等)

    asp.net DataTable相關(guān)操作集錦(篩選,取前N條數(shù)據(jù),去重復(fù)行,獲取指定列數(shù)據(jù)等)

    這篇文章主要介紹了asp.net DataTable相關(guān)操作,包括篩選,取前N條數(shù)據(jù),去重復(fù)行,獲取指定列數(shù)據(jù)等.基本涵蓋了DataTable的常見(jiàn)操作技巧,需要的朋友可以參考下
    2016-06-06
  • ASP.NET Core實(shí)現(xiàn)AES-GCM加密算法

    ASP.NET Core實(shí)現(xiàn)AES-GCM加密算法

    這篇文章介紹了ASP.NET Core實(shí)現(xiàn)AES-GCM加密的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07

最新評(píng)論