2017年12月25日 23:00
原创作品,转载时请务必以超链接形式标明文章原始出处,否则将追究法律责任。

最近比较累,也没时间写博客,今天索性来一篇,很多时候,网站即时通讯,推送必不可少。但是这部分大家都觉得是那么陌生,不敢尝试,今天我就给大家讲讲SignalR的简单使用。


首先我们打开VS,创建一个web应用程序。然后Nuget安装SignalR,如下。

wKiom1dX5_rhvJpuAACHYDs_2-E256.png-wh_50

安装好之后,我们在项目的引用中发现程序给我们自动引用了相关的dll以及js文件。

wKioL1dX6RjBd-iYAAApAdhpdxo726.png-wh_50

wKiom1dX6B_i2-H8AAAenXgKiPQ509.png-wh_50

接着我们创建两个类,一个是ChatHub,继承自Hub,如下

using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
 
namespace Chart.SignalR
{
    [HubName("ChatRoomHub")]
    public class ChatHub : Hub
    {
        static List<UserEntity> users = new List<UserEntity>();
        public async Task UserEnter(string nickName)
        {
            UserEntity userEntity = new UserEntity
            {
                NickName = nickName,
                ConnectionId = Context.ConnectionId
            };
 
            users.Add(userEntity);
            await Clients.All.NotifyUserEnter(nickName, users);
        }
 
        public async Task SendMessage(string nickName, string message)
        {
            await Clients.All.NotifySendMessage(nickName, message);
        }
 
        public override Task OnDisconnected(bool isStop)
        {
            var currentUser = users.FirstOrDefault(u => u.ConnectionId == Context.ConnectionId);
            if (currentUser != null)
            {
                users.Remove(currentUser);
                Clients.Others.NotifyUserLeft(currentUser.NickName, users);
            }
            return base.OnDisconnected(isStop);
        }
    }
 
    public class UserEntity
    {
        public string NickName { get; set; }
 
        public string ConnectionId { get; set; }
    }
}

在这里我们给ChatHub起了别名ChatRoomHub。大家从代码上看就知道我写的将是一个聊天室的代码。这里users用来存储在线人员,NickName存放用户进聊天室之前输入的昵称,ConnectionId则是Hub上下文给每个连接分配的唯一标识,这样方便我们判断用户离线的情况。

在这个Hub子类中,

UserEnter方法用来记录加入聊天的用户,并通知到其他客户端浏览器更新UI。

SendMessage方法用来将客户端发送的消息推送到所有的客户端浏览器。

OnDisconnected顾名思义就是客户端离线,离线后将离线用户从用户数组中删除掉,并通知其他用户浏览器更新UI,注意这里的Clients.Others


接着我们再看一下StartUp类

using Microsoft.Owin;
using Owin;
 
[assembly: OwinStartup(typeof(Chart.SignalR.StartUp))]
namespace Chart.SignalR
{
    public class StartUp
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
        }
    }
}

这里OwinStartup标识了哪个类是自动启动,app.MapSignalR()则是将app builder 管道映射到一个路径上,待会我们会看到这个路径。

OK,接下来我们看下客户端的代码

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <link rel="stylesheet" href="StyleSheet/bootstrap/css/bootstrap.min.css" />
    <script src="Scripts/jquery-1.6.4.min.js"></script>
    <script src="Scripts/jquery.signalR-2.2.0.min.js"></script>
    <script src="Scripts/bootstrap.min.js"></script>
    <script src="signalr/hubs"></script>
    <style>......</style>
</head>
<body>
    <div class="container" style="margin-top: 10px">
        <div class="row">
            <div class="col-md-9">
                <div class="panel panel-primary">
                    <div class="panel-heading">
                        聊天室
                    </div>
                    <div id="div_msgbody" class="panel-body" style='min-height: 500px; max-height: 500px; overflow: auto; max-width: 850px;'>
                        <div id="div_msg" style='word-wrap: break-word; word-break: break-word;'></div>
                    </div>
                    <div class="panel-footer">
                        <div class="row">
                            <div class="col-md-11">
                                <div class="input-group">
                                    <span class="input-group-addon">内容:</span>
                                    <input id="message" type="text" class="form-control" maxlength="500" placeholder='在此输入聊天内容' />
                                </div>
                            </div>
                            <div class="col-md-1">
                                <button id="btn_Send" type="button" class="btn btn-info">发送</button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="col-md-3">
                <div class="panel panel-primary">
                    <div class="panel-heading">
                        用户列表
                    </div>
                    <div class="panel-body" style='min-height: 500px; max-height: 500px; overflow: auto;'>
                        <div id="div_member"></div>
                    </div>
                    <div class="panel-footer">
                        <div style="height: 34px; height: 34px; line-height: 34px">
                            人员总数:<label id="lab_total">0</label>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <script type="text/javascript">
        var userNickName;
        jQuery(document).ready(function () {
            while (!userNickName) {
                userNickName = window.prompt("请输入昵称!");
            }
 
            var chatHub = $.connection.ChatRoomHub;
 
            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://www.wed114.cn/jiehun/uploads/allimg/160426/39_160426110624_1.jpg';
                if (nickName == userNickName) {
                    $("#div_msg").append("<div style='text-align:right;float:right'>"
                    + "<span style='margin-right:10px'>" + nickName + "</span>"
                     + "<img src='" + userAvatar + "' style='height:40px;width:40px;position:relative'/>"
                    + "<div class='demo clearfix fr'>"
                    + "<span class='triangle'></span>"
                    + "<div class='article' style='word'>" + message
                    + "</div></div></div><div class='clear-float'/>");
                }
                else {
                    $("#div_msg").append("<div>"
                     + "<img src='" + userAvatar + "' style='height:40px;width:40px;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>");
                }
 
                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://www.wed114.cn/jiehun/uploads/allimg/160426/39_160426110624_1.jpg';
                    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>
</body>
</html>

布局我就不说了,BootStrap布局。这里需要注意这个路径

<script src="signalr/hubs"></script>

这个路径就是上面说的管道map的路径,在这个路径下会生成hubs.js文件,在这个文件中有注册hub代码,生成hub代理等方法。

wKioL1dX6mKxZq_bAADQt4R1LVk208.png-wh_50

然后在js中,先让用户输入昵称,输入后,得到chatHub对象,然后

实现NotifyUserEnter,NotifyUserLeft以及NotifySendMessage方法。NotifyUserEnter和NotifyUserLeft方法主要是更新右边panel显示的人员信息。而NotifySendMessage方法则是将服务器推送出的聊天信息展示在span中。在这里我们为了区分自己和别人,自己的聊天信息显示在右边,别人的显示在左边。

var objDiv = document.getElementById("div_msgbody");
objDiv.scrollTop = objDiv.scrollHeight;

这句的意思是如果聊天记录太多出现了滚动条,则将滚动条自动滚动到最底部。

$.connection.hub.start().done(function () {        
     chatHub.server.userEnter(userNickName);
});

这句意思是当有新用户时,就会和服务端建立连接,连接完成后,调用Server端的UserEnter方法,在客户端这里写小写开头,记住。最后发送消息,调用server端的SendMessage方法。

OK,至此程序大概就讲完了,很简单的一个demo,大家看了的也评价评价。俗话说无图无真相,看图

wKiom1dX696Ck1xxAAF1JhJYI-o030.png

wKioL1dX7Q3j10uZAAE1TO-yrJc188.png好了今天就到这里,后面我会继续写nodejs相关的博客。

发表评论
匿名  
用户评论
暂无评论