翻译自:http://www.codeproject.com/Articles/562023/Asp-Net-SignalR-Chat-Room  (在这里可以下载到实例的源码)

Asp.Net SignalR 聊天室

简单介绍:
        最近微软向ASP.NET Web Application Framework中添加了很多的新特性,SignalR是其中比较显著的特性之一,它是用来创建实时的应用程序的,例如:社交应用(social application)、多人游戏、新闻天气等,在实时的应用程序中,一旦内容可以产生马上就会被推送给用户,它为远程呼叫(remote procedure calls)提供一个asp.net API,用来在服务器端通过.net代码调用一个客户端浏览器中的js方法。

web应用程序通过请求处理模型来工作,浏览器或者其他的代理发送一个请求,然后服务器端为请求提供相应在这个模型当中,服务器在没有被请去I的时候不能做出响应,然而在实时的应用程序服务器上,最新的可用内容会被推送到客户端你可以通过使用ASP.NET SignalR API 来达到这一特性

为了解释 SignalR Web API ,在这篇文章中,我会创建一个可以群组聊天也可以私聊的聊天程序,你需要用VS2012 来创建这个项目
你在这个网站可以获取更多的信息http://www.asp.net/signalr

让我们开始吧:
        在VS中创建一个新的应用程序项目(web application project ),创建好了以后,右键——添加新项——选择SignalR Hub Class ,命名之后点击添加按钮,它会自动添加 Hub 类,需要的引用,还有脚本。

注册Hub URL
为了使用SignalR API,我们需要注册 ~/signalr/hubs URL,在你的解决方案中添加global.asax文件,在Application_Start方法中用RouteTable.Routes.MapHubs()来注册 Hub URL

public class Global : System.Web.HttpApplication
 {
    protected void Application_Start(object sender, EventArgs e)
    {
        // Register the default hubs route: ~/signalr/hubs
        RouteTable.Routes.MapHubs();
    }

}

Hub 类
ChatHub 类必须继承自Microsoft.AspNet.SignalR.Hub 类,Hub 类暴露出一些属性和方法,你可以通过Clients属性与保持链接的客户端交流
你可以得到正在调用方法使用Contextde 客户端的信息,你也可以通过Groups属性来管理组。

public abstract class Hub : IHub, IDisposable
{
  public HubConnectionContext Clients { get; set; }
  public HubCallerContext Context { get; set; }
  public IGroupManager Groups { get; set; }

public virtual Task OnConnected();       
  public virtual Task OnDisconnected();      
  public virtual Task OnReconnected();

}

子类可以重写Onconnected,OnDisconnected方法,这个对事件触发一些动作是非常有用的,ChatHub 类是Hub类的子类,在接下来的部分我们来讨论它们的方法
 public class ChatHub : Hub
 {
    public void Connect(string userName);

public void SendMessageToAll(string userName, string message);

public void SendPrivateMessage(string toUserId, string message);

public override System.Threading.Tasks.Task OnDisconnected();

.
    .
    .

}   
客户端在他想进入聊天室的时候会调用Connect方法,调用SendMessageToAll方法,他可以向聊天室中保持连接的所有人
通过调用 SendPrivateMessage 方法,key与单独的一个客户端聊天

客户端的代理(Proxy)

在项目中添加index.html 页面,引用JQuery,SignalR、还有自动生成的hubs(?不知道这个指什么)

<script src="http://www.codeproject.com/Scripts/jquery-1.8.2.min.js%22%3E%3C/script>

<!--Reference the SignalR library. -->
 <script src="http://www.codeproject.com/Scripts/jquery.signalR-1.0.0.js%22%3E%3C/script>

<!--Reference the autogenerated SignalR hub script. -->
 <script src="http://www.codeproject.com/signalr/hubs%22%3E%3C/script>

在客户端,你需要创建一个hub 代理(hub proxy)并启动它,一可以通过$.connection.yourHubClass来创建它$.connection.hub.start() 来启动它
 <script type="text/javascript">

$(function () {

// Declare a proxy to reference the hub.
     var chatHub = $.connection.chatHub;

registerClientMethods(chatHub);

// Start Hub
     $.connection.hub.start().done(function () {

registerEvents(chatHub)

});

});

</script>   
在这里我们需要注意的是自动生成的Hub proxy的命名方法,我们在服务器端用Camel命名法给ChatHub类命名,但是在客户端我们得到的是用little camel 方式命名的,就像$.connection.chatHub

连接到聊天室

用户成功的链接之后发送他的名称就可以连接到聊天室,我们会给他发送一个列表,和一些存在我们程序中的最近的聊天记录在ChatHub类中的第一个方法就是Connect

public void Connect(string userName)
 {
    var id = Context.ConnectionId;

if (ConnectedUsers.Count(x => x.ConnectionId == id) == 0)
    {

ConnectedUsers.Add(new UserDetail { ConnectionId = id, UserName = userName });

// send to caller
        Clients.Caller.onConnected(id, userName, ConnectedUsers, CurrentMessage);

// send to all except caller client
        Clients.AllExcept(id).onNewUserConnected(id, userName);
    }
 }

通过Context.ConnectionId属性拿到调用Connect方法的用户的连接Id,在已有的链接列表汇总核对是否已经存在该用户的链接,现在我们还要做两件事,首先,我们要将已连接的客户端的列表和最近的聊天记录发送给想要链接的客户端,然后我们要同通知其他的用户有新人加进来了,我们可以通过Clients.Caller属性来很方便的调用想要连接到聊天室的客户端的方法:

// send to caller
  Clients.Caller.onConnected(id, userName, ConnectedUsers, CurrentMessage);

要通知其他的链接在聊天室的人,但是我们又不想调用新加入的人的方法,可以用Clients的AllExcept属性,它可以按照你的意愿来排除一些客户端
// send to all except caller client
 Clients.AllExcept(id).onNewUserConnected(id, userName);

定义/发布 你在服务器端调用的客户端的方法,做法是声明Clients.Caller.onConnected(...) 和 Clients.AllExcept(id).onNewUserConnected(...)
???You can define your methods using chatHub.client.yourMethodName at client side.

// Calls when user successfully logged in
 chatHub.client.onConnected = function (id, userName, allUsers, messages) {

.
    .
    .

}

// On New User Connected
 chatHub.client.onNewUserConnected = function (id, name) {

AddUser(chatHub, id, name);
 }

用chatHub.server.yourMethod声明, 在客户端,你可以调用服务器端的方法。
chatHub.server.connect(name);

在聊天室中发送消息:
在出聊天室中,用户输入的消息会广播给所有正在连接中的用户,在服务器端的ChatHub类中,写用Clients.All.messageReceived来写 SendMessageToAll方法,
messageReceived是一个客户端的方法。

public void SendMessageToAll(string userName, string message)
 {
    // store last 100 messages in cache
    AddMessageinCache(userName, message);

// Broad cast message
    Clients.All.messageReceived(userName, message);
 }

在客户端引发messageReceived 方法,这个方式只是简单的用JQuery将消息加入到聊天区域

chatHub.client.messageReceived = function (userName, message) {

AddMessage(userName, message);
 }

在写好了客户端和服务器端的方法以后,现在我们要在客户端来注册按钮的点击事件,在用户点击按钮的时候,就会调用服务器端的sendMessageToAll方法,它会广播消息给所有处于连接状态的客户端

$('#btnSendMsg').click(function () {

var msg = $("#txtMessage").val();
     if (msg.length > 0) {

var userName = $('#hdUserName').val();

chatHub.server.sendMessageToAll(userName, msg);
       
         $("#txtMessage").val('');
     }
 });

私聊模式
你也可以通过双击客户端的名称实现私聊,私聊的时候我们不用发信息给所有正在连接的客户端,在私聊的时候,只有两个客户端之间进行通话,所以在发送私人信息的时候,
发送人要调用sendPrivateMessage 方法

public void SendPrivateMessage(string toUserId, string message)
 {

string fromUserId = Context.ConnectionId;

var toUser = ConnectedUsers.FirstOrDefault(x => x.ConnectionId == toUserId) ;
    var fromUser = ConnectedUsers.FirstOrDefault(x => x.ConnectionId == fromUserId);

if (toUser != null && fromUser!=null)
    {
        // send to
        Clients.Client(toUserId).sendPrivateMessage(fromUserId, fromUser.UserName, message);

// send to caller user
        Clients.Caller.sendPrivateMessage(toUserId, fromUser.UserName, message);
    }

}

断开连接:
在浏览器关闭的时候,SignalR API 调用 OnDisconnected 方法,在你的ChatHub类中重写这个方法,
在这个方法中将断开连接的客户端从缓存结合中删除并且向其他的用户发送一个提示。

public override System.Threading.Tasks.Task OnDisconnected()
 {
     var item = ConnectedUsers.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId);
     if (item != null)
     {
         ConnectedUsers.Remove(item);

var id = Context.ConnectionId;
         Clients.All.onUserDisconnected(id, item.UserName);

}

return base.OnDisconnected();
 }

转载于:https://www.cnblogs.com/key1309/p/3398332.html

SignalR 聊天室实例详解(服务器端推送版)相关推荐

  1. vue php聊天室,实例详解vue组件父子间通信之聊天室

    本文主要为大家详细介绍了vue组件父子间通信之综合练习聊天室制作,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能帮助到大家. 组件父子间通信之综合练习 {{msg}} // 创建父组件 Vu ...

  2. GTK+实现linux聊天室代码详解-clientr端

    查看原代码请点击此超链接 注意!!此聊天室对红帽无兼容.需在其他linux系统上运行,如"深度". 加油学习! GTK+实现linux聊天室代码详解-server端:GTK+实现l ...

  3. C/C++实现聊天室(详解版)

    文章目录 一.程序演示 二.项目介绍 三.代码详解 服务器 客户端 一.程序演示 虽然最开始是打算写个局域网就好了的,但其实如果你有云服务器,可以向微信.QQ一样与相隔甚远的朋友聊天,只需要将客户端I ...

  4. php微信小程序物流进度推送,微信小程序 消息推送php服务器验证实例详解

    微信小程序 消息推送php服务器验证实例详解 设置页面("设置">>"开发设置"): 1.设置服务器域名 注意http和https协议的不同. 2. ...

  5. java的websocket_java 实现websocket的两种方式实例详解

    一.介绍 1.两种方式,一种使用tomcat的websocket实现,一种使用spring的websocket 2.tomcat的方式需要tomcat 7.x,JEE7的支持. 3.spring与we ...

  6. 怎样在两个局域网内共享一台打印机 。常用网络命令及命令实例详解

    怎样在两个局域网内共享一台打印机 怎样在两个局域网内共享一台打印机 我们公司有两间办公室,原先布线的时候用一个路由器延伸出多个接口预埋在墙里并做上插头,IP地址是自动分配的,网关是192.168.0. ...

  7. java前端长连接框架_Java中Spring Boot+Socket实现与html页面的长连接实例详解

    Spring Boot+Socket实现与html页面的长连接,客户端给服务器端发消息,服务器给客户端轮询发送消息,附案例源码 功能介绍 客户端给所有在线用户发送消息客户端给指定在线用户发送消息服务器 ...

  8. linux git 删除分支,git 删除分支和回滚的实例详解

    linux shell 的 git 删除分支和回滚的实例详解 git 删除分支和回滚的实例详解 [git 删除本地分支] git branch -D br [git 删除远程分支] git push ...

  9. tcp网络通信教程 java_基于java TCP网络通信的实例详解

    JAVA中设计网络编程模式的主要有TCP和UDP两种,TCP是属于即时通信,UDP是通过数据包来进行通信,UDP当中就会牵扯到数据的解析和传送.在安全性能方面,TCP要略胜一筹,通信过程中不容易出现数 ...

最新文章

  1. 如何估算各种物体的重心
  2. Spring思维导图(MVC篇)
  3. android 拖动数字选择,拖放android 3.x导致illegalStateException之后的小数字拖动
  4. C++ STL实现的优先队列( priority_queue )
  5. hbase 学习(十三)集群间备份原理
  6. DAY06-Python入门学习-元组、字典、集合类型
  7. 每日算法系列【LeetCode 16】最接近的三数之和
  8. Java阶乘中数值溢出
  9. 在线旅游中需要上传获取那些信息,对接旅行社护照录入系统
  10. Centos8 部署Promethus(普罗米修斯)+grafana画图
  11. wsbm服务器错误怎么修复,如何使用ab测试上传文件
  12. 微信群控的服务器怎么用,微信群控开发SDK使用教程--手机客户端返回聊天消息的原始内容给服务端...
  13. 平面设计素材|黑白海报设计,暗黑潮流
  14. bootstrap 5 表单验证
  15. python,根据tkinter计数器案例,写了个倒计时器
  16. 用物理学分析马歇尔的价格均衡论
  17. 常见的H5C3的面试题
  18. cartographer:论文阅读(Real-Time Loop Closure in 2D LIDAR SLAM)
  19. 华展云-让展览更高效 2017第十八届中国国际机床装备展览会会刊(参展商名录)
  20. 开源工业自动化SCADA数据采集系统(基于win2016ser)

热门文章

  1. python 类内置方法
  2. paypal添加香港招商银行指南
  3. 怎样在Linux中用Vim对文件进行密码保护
  4. 函数式编程-将Monad(单子)融入Swift
  5. OCM_第十一天课程:Section5 —》数据仓库
  6. 阿里云服务器创建历史功能介绍 快速创建云服务器
  7. jquery级联下拉框
  8. Android数据库一些源码分析
  9. 搜索 + 剪枝 --- POJ 1101 : Sticks
  10. DB2 常用的SQL