SignalR《二》接着前篇的继续
SignalR《二》接着前篇的继续
SignalR身份验证
在ChatRoomHub加上[Authorize] 这样登录了才能发送消息
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.SignalR;
using SignalRStudy.Entity;
using System.Security.Claims;
namespace SignalRStudy.Hubs
{
[Authorize]
public class ChatRoomHub : Hub
{
private readonly UserManager<MyUser> _userManager;
public ChatRoomHub(UserManager<MyUser> userManager)
{
_userManager = userManager;
}
//SignalR的基本使用
public Task SendPublicMessage(string messgae)
{
//获取当前连接id
var connid = this.Context.ConnectionId;
var msg = $"{connid}:{DateTime.Now}发送了{messgae}";
//SendAsync 是对SendCoreAsync的封装
//对所有人发送消息 只有一个异步方法可以 不屑async 和 await
//ReceivePublicMessage 为前端接受消息方法
var res = Clients.All.SendAsync("ReceivePublicMessage", msg);
return res;
}
public async Task<string> SendPrivateMessage(string destUserName, string message)
{
var destUser = await _userManager.FindByNameAsync(destUserName);
if (destUser == null)
{
return "DestUserNotFound";
}
string destUserId = destUser.Id.ToString();
string srcUserName = this.Context.User!.FindFirst(ClaimTypes.Name)!.Value;
string time = DateTime.Now.ToShortTimeString();
await this.Clients.User(destUserId).SendAsync("ReceivePrivateMessage",
srcUserName, time, message);
return "ok";
}
}
}
如下图
前端代码(前端 Vue3 我不是很熟,不多讲了)
<template>
<fieldset>
<legend>登录</legend>
<div>
用户名:<input type="text" v-model="state.loginData.userName"/>
</div>
<div>
密码:<input type="password" v-model="state.loginData.password">
</div>
<div>
<input type="button" value="登录" v-on:click="loginClick"/>
</div>
</fieldset>
公屏:<input type="text" v-model="state.userMessage" v-on:keypress="txtMsgOnkeypress" />
<div>
私聊给<input type="text" v-model="state.privateMsg.destUserName"/>
说<input type="text" v-model="state.privateMsg.message"
v-on:keypress="txtPrivateMsgOnkeypress"/>
</div>
<div>
<ul>
<li v-for="(msg,index) in state.messages" :key="index">{{msg}}</li>
</ul>
</div>
</template>
<script>
import { reactive, onMounted } from 'vue';
import * as signalR from '@microsoft/signalr';
import axios from 'axios';
let connection;
export default {name: 'Login',
setup() {
const state = reactive({accessToken:"",userMessage: "", messages: [],
loginData: { userName: "", password: "" },
privateMsg: { destUserName:"",message:""},
});
const startConn = async function () {
const transport = signalR.HttpTransportType.WebSockets;
const options = { skipNegotiation: true, transport: transport };
options.accessTokenFactory = () => state.accessToken;
connection = new signalR.HubConnectionBuilder()
.withUrl('https://localhost:7298/Hubs/ChatRoomHub', options)
.withAutomaticReconnect().build();
try {
await connection.start();
} catch (err) {
alert(err);
return;
}
connection.on('ReceivePublicMessage', msg => {
state.messages.push(msg);
});
connection.on('ReceivePrivateMessage', (srcUser,time,msg) => {
state.messages.push(srcUser+"在"+time+"发来私信:"+msg);
});
connection.on('UserAdded', userName => {
state.messages.push("系统消息:欢迎" + userName+"加入我们!");
});
alert("登陆成功可以聊天了");
};
const loginClick = async function () {
const resp = await axios.post('https://localhost:7298/api/Test/Login',
state.loginData);
state.accessToken = resp.data;
startConn();
};
const txtMsgOnkeypress = async function (e) {
if (e.keyCode != 13) return;
try {
await connection.invoke("SendPublicMessage", state.userMessage);
}catch (err) {
alert(err);
return;
}
state.userMessage = "";
};
const txtPrivateMsgOnkeypress = async function (e) {
if (e.keyCode != 13) return;
const destUserName = state.privateMsg.destUserName;
const msg = state.privateMsg.message;
try {
const ret = await connection.invoke("SendPrivateMessage", destUserName, msg);
if (ret != "ok") { alert(ret);};
} catch (err) {
alert(err);
return;
}
state.privateMsg.message = "";
};
return { state, loginClick, txtMsgOnkeypress, txtPrivateMsgOnkeypress };
},
}
</script>
<style scoped>
</style>
总结:
对应的方法名和后端对应,参数都对应即可
外部向SignalR的Hub发送消息
TestController代码
[HttpPost]
public async Task<IActionResult> SendMsgToUser(AddNewUserRequest req)
{
//查询用户
var user = await _userManager.FindByNameAsync(req.UserName);
if (user == null)
{
return BadRequest($"查无此人{req.UserName}");
}
var pm = await _userManager.FindByNameAsync("PM");
string time = DateTime.Now.ToShortTimeString();
string msg = @"PM,我来了";
//这是给PM发送消息
await _hubContext.Clients.User(pm.Id.ToString()).SendAsync("ReceivePrivateMessage", req.UserName,time, msg);
return Ok(req.UserName+"存在");
}
本来应该是添加一个用户,然后给PM(领导)自动发个消息,手下来新人了。 复制的AddUser方法,不想再添加用户了,所以虽然是Post请求 ,我只是查询了数据库是否有此人,然后给PM发了消息。只是单纯学习演示下功能。
测试结果如下
SignalR向部分客户端发消息
上述代码其实已经包含了向部分客户端发消息,不过是以调用接口然后发送,下面的是加上前端实现的类似于私聊的功能。
ChatRoomHub里面的SendPrivateMessage方法已经上面的写了,前端只写了一个方法接受ReceivePrivateMessage,在上述前端代码中,不影响渲染。
测试结果如下
SignalR综合案例
我就不贴代码了:使用场景是
英汉词典ECDICT中导入单词到数据库。
下载地址:https://github.com/skywind3000/ECDICT/blob/master/stardict.7z
是一个csv文件,目的就是把这个文件读取出来然后存到数据库里面,数据量比较大,通过SignalR通知前端,完成一个进度条的功能。
核心就是 list< entity >存到数据库里面
当前插入条数/总条数
不要一下全部插入,分批量 100或者1000、10000都可以看自己
前端progress就可以通过百分比来形成进度条。
提示:EF Core 目前还不支持批量处理(里面还是一条一条的 ,学习的话 这样也可以)
如果要批量 可以使用sqlbulk或者使用这个https://github.com/yangzhongke/Zack.EFCore.Batch
本文内容大部分都为杨中科老师《ASP.NET Core技术内幕与项目实战》一书中内容,此文只是做学习记录,如有侵权,联系立马删除。
SignalR《二》接着前篇的继续的更多相关文章
- 数据库索引<二> 补充前篇 (上一篇抽风了,这个补上)
在前一个创建索引中已经大概说了三部分的影响,基本应该注意哪一些.写完上一篇后我感觉有很多地方没有写清楚,所以这篇就是更深入一些的理解索引到底是怎么和数据表关联,怎么快速查询的. 先看一下下面的图,图是 ...
- 数据库索引<二> 补充前篇
你要准备的软件有: 最新版 Rsync for windows 服务端:cwRsync_Server_2.1.5_Installer.zip 客户端:cwRsync_2.1.5_Installer.z ...
- 前端面试题总结(二)CSS篇
前端面试题总结(二)CSS篇 一.link和@import的区别? link属于HTML标签,可以引入出css以外的事务,如RSS,而@import是css提供的,只能加载css文件. link会在页 ...
- Linux负载均衡软件LVS之二(安装篇)[转]
Linux负载均衡软件LVS之二(安装篇) 2011-04-26 16:01:47 标签:lvs安装配置 linux lvs 休闲 linux高可用 原创作品,允许转载,转载时请务必以超链接形式标明文 ...
- 【原创】构建高性能ASP.NET站点 第六章—性能瓶颈诊断与初步调优(下前篇)—简单的优化措施
原文:[原创]构建高性能ASP.NET站点 第六章-性能瓶颈诊断与初步调优(下前篇)-简单的优化措施 构建高性能ASP.NET站点 第六章—性能瓶颈诊断与初步调优(下前篇)—简单的优化措施 前言:本篇 ...
- [原创].NET 分布式架构开发实战之四 构建从理想和实现之间的桥梁(前篇)
原文:[原创].NET 分布式架构开发实战之四 构建从理想和实现之间的桥梁(前篇) .NET 分布式架构开发实战之四 构建从理想和实现之间的桥梁(前篇) 前言:上一篇文章讲述了一些实现DAL的理论,本 ...
- 隐马尔科夫模型HMM(二)前向后向算法评估观察序列概率
隐马尔科夫模型HMM(一)HMM模型 隐马尔科夫模型HMM(二)前向后向算法评估观察序列概率 隐马尔科夫模型HMM(三)鲍姆-韦尔奇算法求解HMM参数(TODO) 隐马尔科夫模型HMM(四)维特比算法 ...
- jQuery-Selectors(选择器)的使用(二、层次篇)(转载)
原文:http://www.cnblogs.com/bynet/archive/2009/12/01/1614405.html 本系列文章导航 jQuery-Selectors(选择器)的使用(一.基 ...
- [知乎]老狼:深入PCI与PCIe之二:软件篇
深入PCI与PCIe之二:软件篇 https://zhuanlan.zhihu.com/p/26244141 我们前一篇文章(深入PCI与PCIe之一:硬件篇 - 知乎专栏)介绍了PCI和PCIe的硬 ...
- Android深入四大组件(四)Android8.0 根Activity启动过程(前篇)
前言 在几个月前我写了Android深入四大组件(一)应用程序启动过程(前篇)和Android深入四大组件(一)应用程序启动过程(后篇)这两篇文章,它们都是基于Android 7.0,当我开始阅读An ...
随机推荐
- shell脚本:报错syntax error near unexpected token `$'\r''解决方法
之前的shell脚本是在服务器上编写的,后来又已复制的方式存在在了电脑上,以txt文件的形式存放的.于是复制到了编辑工具中,进行了相应项的修改.修改完毕后,拿到服务器上测试,结果执行sh XXX.sh ...
- A Novel Cross-domain Access Control Protocol in Mobile Edge Computing
摘要 随着智能移动终端和移动通信技术的发展,移动边缘计算(MEC)已经应用到各个领域.然而,MEC也带来了新的数据安全威胁,包括数据访问威胁.针对MEC中的跨域访问控制问题,提出一种跨域访问控制协议C ...
- ipvsadm DR模型的实现方式
DR模型的lvs ----在实现DR模型的时候所有RS都要屏蔽掉ARP请求的响应 实现方法:1.可以用路由器绑定静态VIP:MAC(DVIP)2.可以使用arptables3.可以使用 kernel ...
- 搭建Redis高可用集群的哨兵模式(Redis-Sentinel)【Windows环境】
参考 https://blog.csdn.net/itanping/article/details/100544152 哨兵模式搭建好,Java中配置和使用Redis高可用集群的哨兵模式,引入Jedi ...
- mysql 的 json 类型
MySQL的 json 数据类型 MySQL5.7 后的版本,添加了对于 json 类型的支持.此前,json 类型的数据,只能在代码层面做 json.loads() 和 json.dumps() 操 ...
- nodejs配合jwt
使用npm下载包: npm i jsonwebtoken --save 引入此包: const jsonwebtoken =require('jsonwebtoken'); JWT的组成: JWT由三 ...
- main(调用一个公共组件)
app.vue <template> <div> <Student/> <School></School> </div> < ...
- C++快速求解最大公因数 | gcd库函数
1.介绍 gcd全称 :greatest common divisor 使用 __gcd( int x1, int x2 ) 函数可以高效.迅速得到x1, x2两个数的最大公因数.省去手写底层代码,专 ...
- gitea安装部署
安装gitea前需要先安装好git,具体参考https://www.cnblogs.com/magicMaQaQ/p/16062312.html 1.安装数据库,gitea支持多种数据库,这里选择my ...
- springboot 集成poi导出word(一)
使用ruoyi-前后端分离版本,根据word模板导出,包含表格和图片. 一.创建模板 列表使用{{}},文本使用[] 二.引入依赖 <!-- excel工具 --> <depende ...