[C#]SignalR实现扫码登录(B/S,C/S)(一)——服务端搭建

4 篇文章 1 订阅
4 篇文章 0 订阅

目录

一、创建项目

二、安装Package

三、实现操作类

3.1 新建类 MyHub.cs、ClientInfo.cs、Helper.cs

3.2 在Program.cs声明公开静态对象

3.3 完善MyHub类

3.4创建启动类

3.5程式入口启动服务

3.6创建扫码成功调用API

四、了解WebAPI和搭建Windows服务

五、相关文章


直入主题

一、创建项目

先创建一个控制台应用程序用来搭建扫码登陆的服务端

二、安装Package

使用Nuget安装以下Package

Microsoft.AspNet.SignalR.SelfHost     ——用于构建自承载的SignalR服务

Microsoft.AspNet.WebApi.Owin    ——用于提供WebApi服务

Microsoft.Owin.Cors  ——用于跨域设置

以上包有依赖项,需要全部引入,引用完成后的packages.config文件如下:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Microsoft.AspNet.Cors" version="5.0.0" targetFramework="net452" />
  <package id="Microsoft.AspNet.SignalR.Core" version="2.4.1" targetFramework="net452" />
  <package id="Microsoft.AspNet.SignalR.SelfHost" version="2.4.1" targetFramework="net452" />
  <package id="Microsoft.AspNet.WebApi.Client" version="5.2.7" targetFramework="net452" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.2.7" targetFramework="net452" />
  <package id="Microsoft.AspNet.WebApi.Owin" version="5.2.7" targetFramework="net452" />
  <package id="Microsoft.Owin" version="4.1.1" targetFramework="net452" />
  <package id="Microsoft.Owin.Cors" version="4.1.1" targetFramework="net452" />
  <package id="Microsoft.Owin.Diagnostics" version="2.1.0" targetFramework="net452" />
  <package id="Microsoft.Owin.Host.HttpListener" version="2.1.0" targetFramework="net452" />
  <package id="Microsoft.Owin.Hosting" version="2.1.0" targetFramework="net452" />
  <package id="Microsoft.Owin.Security" version="2.1.0" targetFramework="net452" />
  <package id="Microsoft.Owin.SelfHost" version="2.1.0" targetFramework="net452" />
  <package id="Newtonsoft.Json" version="6.0.4" targetFramework="net452" />
  <package id="Owin" version="1.0" targetFramework="net452" />
</packages>

我这边准备搭建的是一个自承载式的服务,所以引用的的是Microsoft.AspNet.SignalR.SelfHost。如果你准备使用IIS搭建服务,可以直接引用Microsoft.AspNet.SignalR

三、实现操作类

通讯模型Hub(中心模型,或者叫集线器模型),它是一种RPC模式,允许客户端和服务器端各自自定义方法并且相互调用。是SignalR的灵魂所在

3.1 新建类 MyHub.cs、ClientInfo.cs、Helper.cs

我们新建一个MyHub类继承Microsoft.AspNet.SignalR.Hub

再建一个 ClientInfo 类 用于存储客户端信息

再建一个 Helper类 用于实现辅助方法

我们这三个类建在合适的路径下

其中Helper.cs和ClientInfo.cs 现在代码比较简单,我直接贴一下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SignalRService.Class
{
    public static class Helper
    {
        /// <summary>
        /// 获取UUID
        /// </summary>
        /// <returns></returns>
        public static string GetUUID() {
            return Guid.NewGuid().ToString();

            //产生的UUID为 字母+数字
            //return Guid.NewGuid().ToString("N");
        }

    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SignalRService.Model
{
    public  class ClientInfo
    {
        public string UUID { get; set; }

        public string ConnectionId { get; set; }
    }
}

3.2 在Program.cs声明公开静态对象

我们在Program.cs 里声明两个静态的对象,因为这两个对象会在全局中使用,其中 MyHub无需实例化,因为在稍后服务启动的时候会对它进行赋值。

using SignalRService.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SignalRService
{
    class Program
    {
        public static List<ClientInfo> ClientInfoList = new List<ClientInfo>();
        public static MyHub MyHub;
        static void Main(string[] args)
        {
        }
    }
}

3.3 完善MyHub类

我把想说的东西都放注释里,这边就直接贴代码

using Microsoft.AspNet.SignalR;
using SignalRService.Class;
using SignalRService.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SignalRService
{
    public class MyHub : Hub
    {
        /// <summary>
        /// 构造时对Program.MyHub赋值
        /// </summary>
        public MyHub()
        {
            Program.MyHub = this;
        }

        /// <summary>
        /// 实现推送扫码成功的用户信息的方法
        /// </summary>
        /// <param name="connectionId"></param>
        /// <param name="userInfo"></param>
        public void SendUserInfo(string connectionId, string userInfo) {
            //调用客户端的 GetUserInfo 方法 返回用户信息
            Clients.Client(connectionId).GetUserInfo(userInfo);
        }
        

        /// <summary>
        /// 实现注册方法
        /// </summary>
        public void Register()
        {
            //获取UUID
            var UUID = Helper.GetUUID();
            //查询用户
            var client = Program.ClientInfoList.Where(u => u.ConnectionId == Context.ConnectionId).SingleOrDefault();
            if (client == null)
            {
                client = new ClientInfo()
                {
                    ConnectionId = Context.ConnectionId,
                    UUID = UUID
                };
                Program.ClientInfoList.Add(client);
            }
            else
            {
                client.UUID = UUID;
            }

            //调用客户端的 GetUUID 方法 返回UUID
            Clients.Client(Context.ConnectionId).GetUUID(Newtonsoft.Json.JsonConvert.SerializeObject(new
            {
                IsOk = "Y",
                Msg = "",
                UUID = UUID
            }));
            //Helper.Log("LoginLog" + System.DateTime.Now.ToString("yyyyMMdd"), "[Register]    " + Newtonsoft.Json.JsonConvert.SerializeObject(client));
        }

        
        /// <summary>
        /// 重写连接事件 目前没实现功能,你可以在这记日志或者干点别的事情
        /// </summary>
        /// <returns></returns>
        public override Task OnConnected()
        {
            //Helper.Log("ConnectedLog" + System.DateTime.Now.ToString("yyyyMMdd"), "[Connected]    [ConnectionId:" + Context.ConnectionId + "  IP:" + Helper.GetClientIp(Context) + "]");
            return base.OnConnected();
        }

        /// <summary>
        /// 重写连接断开事件
        /// </summary>
        /// <param name="stopCalled"></param>
        /// <returns></returns>
        public override Task OnDisconnected(bool stopCalled)
        {
            //查询用户
            var client = Program.ClientInfoList.Where(u => u.ConnectionId == Context.ConnectionId).SingleOrDefault();
            //判断用户是否存在,存在则删除
            if (client != null)
            {
                //删除用户
                Program.ClientInfoList.Remove(client);
            }
            //Helper.Log("ConnectedLog" + System.DateTime.Now.ToString("yyyyMMdd"), "[Disconnected]    " + Newtonsoft.Json.JsonConvert.SerializeObject(client));

            return base.OnDisconnected(stopCalled);
        }
    }
}

3.4创建启动类

我们需要先引用一个框架库 System.Web.Http

贴代码

using Microsoft.AspNet.SignalR;
using Microsoft.Owin.Cors;
using Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;

namespace SignalRService
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            HttpConfiguration config = new HttpConfiguration();

            //配置Api;路由
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            app.UseCors(CorsOptions.AllowAll);//设置Api允许跨域
            app.MapSignalR(new HubConfiguration() { EnableJSONP = true });//启用SignalR 并启用JSONP(保证跨域数据传输)

            app.UseWebApi(config);//启动WebApi
        }
    }
}

3.5程式入口启动服务

修改Program.cs文件 启动服务

using Microsoft.Owin.Hosting;
using SignalRService.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SignalRService
{
    class Program
    {
        public static List<ClientInfo> ClientInfoList = new List<ClientInfo>();
        public static MyHub MyHub;
        static void Main(string[] args)
        {
            WebApp.Start<Startup>("http://localhost:9999");
            Console.Write("SignalRService Started!");
            Console.ReadKey();
        }
    }
}

好了,到这一步,我们的服务就搭建好了,跑起来试一下(这里是使用localhost启动的服务,如果想以IP启动,供网域内电脑访问,需要以管理员身份运行)

服务启动没有问题。

我们访问  http://localhost:9999/signalr/hubs 成功,SignalR服务运行正常

3.6创建扫码成功调用API

在上边我们的SignalR 服务已经搭建好了,现在我们还缺少一个扫码成功调用的接口,其实刚刚我们已经配置好了API的路由和启动方法。所以下面我们直接来写接口,根据我们刚刚设置的路由规则【routeTemplate: "api/{controller}/{id}"】,我们需要把接口写在Controller 文件夹下

我在这里建了两个接口:QRLogin用于接收登录请求;SayHello用于测试

继续贴代码:

using System.Web.Http;

namespace SignalRService.Controller
{
    public class SayHelloController : ApiController
    {
        [HttpGet]
        public string SayHello() {
            return "Hello World!";
        }
    }
}
using System.Linq;
using System.Web.Http;

namespace SignalRService.Controller
{
    public class QRLoginController : ApiController
    {
        [HttpGet]
        public string QRLgoin(string uuid, string userInfo)
        {
            var client = Program.ClientInfoList.Where(u => u.UUID == uuid).SingleOrDefault();
            if (client != null)
            {
                Program.MyHub.SendUserInfo(client.ConnectionId, userInfo);
                Program.ClientInfoList.Remove(client);

                return "登录成功,登录结果:" + userInfo;
            }
            return "登录失败,二维码已过期";
        }
    }
}

接口写好了,我们重新启动一下程式,成功。

来验证一下接口:http://localhost:9999/api/SayHello

也没有问题。

好的本章就写到这里

四、了解WebAPI和搭建Windows服务

现在我们写的服务是一个控制台应用程序,启动时才能提供服务,还容易被不小心关掉,你可以把它做成Windows服务安装在Windows上

如果你想了解WebAPI和搭建Windows服务,可以参考我以前写的文章

WebApi多版本管控和插件式开发(一)——WebApi服务搭建

五、相关文章

 

[C#]SignalR实现扫码登录(B/S,C/S)

[C#]SignalR实现扫码登录(B/S,C/S)(一)——服务端搭建

[C#]SignalR实现扫码登录(B/S,C/S)(二)——客户端搭建(Web版)

[C#]SignalR实现扫码登录(B/S,C/S)(三)——客户端搭建(WinForm版)

[C#]SignalR实现扫码登录(B/S,C/S)源码​​​​​​​

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值