C# SignalR 即时通讯 聊天室
一.SignalR简介
SignalR:当所连接的客户端变得可用时服务器代码可以立即向其推送内容,而不是让服务器等待客户端请求新的数据。实现实时服务器与客户端通信。是一个开源.NET 库生成需要实时用户交互或实时数据更新的 web 应用程序。
SignalR的出现,让页面通过javascript可以很简单的调用后端服务的方法,而在后端也可以很简单的直接调用javascript所实现的方法,前后端可以进行实时通信。实现了服务器主动推送(Push)消息到客户端页面,这样客户端就不必重新发送请求或使用轮询技术来获取消息。
注意:SignalR 会自动管理连接。客户端和服务器之间的连接是持久性的,不像传统的 HTTP 连接。
二.SignalR传输方式
SignalR会根据当前浏览器自动选择适当的传输方式。在最坏的情况下,SignalR会选择使用长轮询(Long Polling).
SignalR会依照下列顺序来判定使用那种传输方式:
- 1.如果浏览器是 Internet Explorer8 或更早版本,则使用长轮询。
- 2.如果配置了 JSONP(即连接启动时 jsonp 参数设置为 true),则使用长轮询。
- 3.如果要建立跨域连接(即 SignalR 终结点和宿主页不在相同的域中),并且满足以下条件,则会使用 WebSocket:
- 3.1客户端支持 CORS(跨域资源共享)
- 3.2客户端支持 WebSocket
- 3.3服务器支持 WebSocket
- 如果这些条件中的任何一条不满足,将使用长轮询.
- 4.如果未配置 JSONP 并且连接没有跨域,只要客户端和服务器都支持的话,将使用 WebSocket。
- 5.如果客户端或服务器不支持 WebSocket,则尽量使用服务器发送事件。Forever Frame。
- 7.如果 Forever Frame 失败,则使用长轮询。
长轮询(long polling)与传统Ajax的不同之处:
- 1.服务器端会阻塞请求直到有数据传递或超时才返回。
- 2.客户端 JavaScript 响应处理函数会在处理完服务器返回的信息后,再次发出请求,重新建立连接。
- 3.当客户端处理接收的数据、重新建立连接时,服务器端可能有新的数据到达;这些信息会被服务器端保存直到客户端重新建立连接,客户端会一次把当前服务器端所有的信息取回。
三.SignalR使用(个人理解)
下面是聊天室的主要代码:
C#代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; //工具 -> 库程序包管理器 -> 程序包管理器控制台 输入下面命令
//install-package Microsoft.AspNet.SignalR -Version 1.1.4
using Microsoft.AspNet.SignalR;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR.Hubs; namespace SignalR.Controllers
{
[HubName("ChatRoomHub")]
public class ChatHub : Hub
{
static List<UserEntity> users = new List<UserEntity>(); /// <summary>
/// 添加用户
/// </summary>
/// <param name="nickName"></param>
public void UserEnter(string nickName)
{
UserEntity userEntity = new UserEntity
{
NickName = nickName,
ConnectionId = Context.ConnectionId
}; users.Add(userEntity);
Clients.All.NotifyUserEnter(nickName, users);//调用前台NotifyUserEnter方法
} /// <summary>
/// 发送消息
/// </summary>
/// <param name="nickName"></param>
/// <param name="message"></param>
public void SendMessage(string nickName, string message)
{
Clients.All.NotifySendMessage(nickName, message);//调用前台NotifySendMessage方法
} /// <summary>
/// 断开(刷新页面可以触发此方法)
/// </summary>
/// <returns></returns>
public override Task OnDisconnected()
{
var currentUser = users.FirstOrDefault(u => u.ConnectionId == Context.ConnectionId);
if (currentUser != null)
{
users.Remove(currentUser);
Clients.Others.NotifyUserLeft(currentUser.NickName, users);//调用前台NotifyUserLeft方法
}
return base.OnDisconnected();
}
} public class UserEntity
{
public string NickName { get; set; } public string ConnectionId { get; set; }
} public class BaseController : Controller
{
/// <summary>
/// 聊天室
/// </summary>
/// <returns></returns>
public ActionResult BroadcastTest()
{
return View();
}
}
}
前台主要JavaScript代码:
<script type="text/javascript">
var userNickName;//昵称
var notification;//消息 jQuery(document).ready(function () {
//没有用户名弹出输入框
while (!userNickName) {
userNickName = window.prompt("请输入昵称!");
} var chatHub = $.connection.ChatRoomHub;//对应后台的类ChatHub //添加用户
chatHub.client.NotifyUserEnter = function (nickName, users) {
buildUserTemplate(users);
} //用户离开
chatHub.client.NotifyUserLeft = function (nickName, users) {
buildUserTemplate(users);
} //处理消息内容
chatHub.client.NotifySendMessage = function (nickName, message) {
var userAvatar = 'http://forum.csdn.net/PointForum/ui/scripts/csdn/Plugin/001/face/29.gif';
//判断消息归属
if (nickName == userNickName) {
$("#div_msg").append("<div style='text-align:right;'>"
+ "<div float:right> <span style='margin-right:10px'>" + nickName + "</span>"
+ "<img src='" + userAvatar + "' style='height:30px;width:30px;position:relative'/>"
+ "<div class='demo clearfix fr'>"
+ "<span class='triangle'></span>"
+ "<div class='article' style='word'>" + message
+ "</div></div></div></div><div class='clear-float'/>");
}
else {
$("#div_msg").append("<div>"
+ "<img src='" + userAvatar + "' style='height:30px;width:30px;position:relative'/>"
+ "<span style='left:10px;position:relative'>" + nickName + "</span>"
+ "<div class='demo clearfix'>"
+ "<span class='triangle'></span>"
+ "<div class='article'>" + message
+ "</div></div></div>");
}
//消息弹出框
if (Notification.permission == "granted") {
notification = new Notification(nickName, {
body: message,
icon: userAvatar,
renotify: true,
tag: 1,
noscreen: true
}); notification.onclick = function () {
notification.close();
};
} else if (Notification.permission != "denied") {
Notification.requestPermission(function (permission) {
notification = new Notification(nickName, {
body: message,
icon: userAvatar,
renotify: true,
tag: 1,
noscreen: true
}); notification.onclick = function () {
notification.close();
};
});
}
var objDiv = document.getElementById("div_msgbody");
objDiv.scrollTop = objDiv.scrollHeight;
} $.connection.hub.start().done(function () {
chatHub.server.userEnter(userNickName);
}); //聊天框发送消息
$("#message").keydown(function (event) {
if (event.keyCode == 13) {
if ($("#message").val() != "") {
chatHub.server.sendMessage(userNickName, $("#message").val());
$("#message").val("");
}
}
}); //发送按钮
$("#btn_Send").click(function () {
if ($("#message").val() != "") {
chatHub.server.sendMessage(userNickName, $("#message").val());
$("#message").val("");
}
}); //用户列表
function buildUserTemplate(users) {
$("#lab_total").text(users.length);
var userTemplate = "<ul style='list-style:none;'>"
$.each(users, function (e, v) {
var userAvatar = 'http://forum.csdn.net/PointForum/ui/scripts/csdn/Plugin/001/face/29.gif';
userTemplate += "<li style='padding-top:5px;'>"
+ "<img class='round-img-list' src='" + userAvatar + "'/>"
+ "<label style='color:#666666;margin-left:10px'>" + v.NickName + "</label>"
+ "</li>";
}); userTemplate += "</ul>"; $("#div_member").html(userTemplate);
}
});
</script>
完整SignalR的源码(包括聊天室,进度条)(我用的vs2013):
百度网盘:链接: https://pan.baidu.com/s/1gf7s5oB 密码: mdi2
最后:
1、Clients.All.NotifySendMessage(nickName, message);调用的是前台JschatHub.client.NotifySendMessage = function (nickName, message) {}这段代码。
2、javascript中,注意使用client和server关键字来调用前端方法和后端方法。
聊天室例子:
下面是进度条例子:
广播例子:
相关文章:http://www.cnblogs.com/frozenzhang/p/5406773.html
C# SignalR 即时通讯 聊天室的更多相关文章
- 黑科技!仅需 3 行代码,就能将 Gitter 集成到个人网站中,实现一个 IM 即时通讯聊天室功能?
欢迎关注个人微信公众号: 小哈学Java, 文末分享阿里 P8 高级架构师吐血总结的 <Java 核心知识整理&面试.pdf>资源链接!! 个人网站: https://www.ex ...
- Openfire XMPP Smack RTC IM 即时通讯 聊天 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- 分享一个基于长连接+长轮询+原生的JS及AJAX实现的多人在线即时交流聊天室
实现网页版的在线聊天室的方法有很多,在没有来到HTML5之前,常见的有:定时轮询.长连接+长轮询.基于第三方插件(如FLASH的Socket),而如果是HTML5,则比较简单,可以直接使用WebSoc ...
- SignalR实现在线聊天室功能
一.在线聊天室 1.新建解决方案 SignalROnlineChatDemo 2.新建MVC项目 SignalROnlineChatDemo.Web (无身份验证) 3.安装SignalR PM> ...
- java Activiti6 工作流引擎 websocket 即时聊天 SSM源码 支持手机即时通讯聊天
即时通讯:支持好友,群组,发图片.文件,消息声音提醒,离线消息,保留聊天记录 (即时聊天功能支持手机端,详情下面有截图) 工作流模块---------------------------------- ...
- .Net core 3.0 SignalR+Vue 实现简单的即时通讯/聊天IM (无jq依赖)
.Net core 中的SignalR JavaScript客户端已经不需要依赖Jquery了 一.服务端 1.nuget安装 Microsoft.AspNetCore.SignalR 2.在star ...
- 使用ASP.NET MVC Web SignalR 构建单身聊天室(一)
前言:本系列的头章,想要带大家一起学习Web SignalR,那它是什么呢?ASP .NET SignalR 是一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信.什么 ...
- .NET之消息推送(SignalR即时通讯实现)
前言 ASP .NET SignalR 是一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信.什么是实时通信的Web呢?就是让客户端(Web页面)和服务器端可以互相通知 ...
- xmpp实现的即时通讯聊天(二)
参考网址:http://www.jianshu.com/p/8894a5a71b70 借图描述原理: 三.注册.登陆.聊天功能的实现 故事板如下: 四个类如下: 不喜多言,直接上Demo: Login ...
随机推荐
- 解决:ADODB.Stream 错误 '800a0bbc' 写入文件失败
重装更改目录为e盘后,上传文件出现问题.解决方法: 调用adodb.stream的savetofile方法时发生错误, ADODB.Stream 错误 800a0bbc 写入文件失败.(msxml3. ...
- AngularJS orderBy 使用要点
AngularJS orderBy 使用要点总结: 1,书写格式 基本应用格式为: ng-repeat="item in itemList | orderBy:p1:p2" 参数p ...
- 软件设计模式之模板方法模式(JAVA)
什么是模板方法模式? 定义一个操作中算法的骨架,而将这些步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤. 好抽象的概念啊,文绉绉的东西就是不讨人喜欢,下面我 ...
- (转)Java程序员应该知道的10个调试技巧
(转自 酷勤网 – 程序员的那点事!http://www.kuqin.com/) 试可以帮助识别和解决应用程序缺陷,在本文中,作者将使用大家常用的的开发工具Eclipse来调试Java应用程序.但这里 ...
- 【WP8】ScrollViewer滑动到底触发器(ListBox失效)
很多时候会有到底加载更多的需求,而ScrollViewer不支持继承,无法继承它进行扩展,只能通过触发器来控制到底的事件(当然,可以通过UserControl去扩展) 思路:定义一个Trigger,自 ...
- 使用 Python 解数学方程
SymPy是符号数学的Python库.它的目标是成为一个全功能的计算机代数系统,同时保持代码简洁.易于理解和扩展 服务器Ubuntu 1.安装Python 2.安装SymPy库 sudo pip in ...
- c# 通过.net自带的chart控件绘制饼图pie chart
c# 通过.net自带的chart控件绘制饼图pie chart 需要实现的目标是: 1.将数据绑定到pie的后台数据中,自动生成饼图. 2.生成的饼图有详细文字的说明. 具体的实现步骤: > ...
- IOS私有API的使用(转)
最近在做企业级程序,需要搞设备的udid等信息,但是ios7把udid私有化了,不公开使用.所以研究了一下ios的私有api. 调查了一下文章,发现这方面的文章不多,国内更是不全,高手们都懒得写基 ...
- OpenGL 知识二
OpenGL综述 September 14, 2014 学习OpenGL是学习计算机图形学的一个工具,因为计算机上图形的显示要依靠底层的软件和硬件,学习图形学除了学习基本的概念,线,曲面,图形生成,变 ...
- 原创:超简单!windows配置NDK开发环境使用JNI
前段时间看android版的opencv的配置教程时,看到了它的NDK配置方法,感觉简单又不会出错!!! 1.下载NDK,设置NDK路径: 在windows的系统环境变量中添加NDK的路径,环境变量名 ...