BeetleX之快速构建Web多房间聊天室
其实构建一个Web
多房间聊天室也并不是什么困难的技术,借助于websocket
就可以轻松实现多用户在线实时通讯交互;在这里主要介绍一下在BeetleX
和BeetleXjs
的支持下如何让这个功能实现的更简单和高效。接下来通过使用BeetleX
来一步步讲解Web多房间聊天室的具体实现。
信息逻辑
既然是多房间聊天室那它具备两个主要元素,分别是用户和房间;下面通过类来描述这两个元素:
用户
public class User
{
public string Name { get; set; } public string Address { get; set; } [JsonIgnore]
public ISession Session { get; set; } [JsonIgnore]
public Room Room { get; set; } public void Send(BeetleX.FastHttpApi.WebSockets.DataFrame frame)
{
frame.Send(Session);
} public void Exit()
{
Room?.Exit(this);
}
}
信息描述比较简单主要包括信息用:名称,会话和房间;涉及的行为有发送信息和退出房间。
房间
public class Room
{ public string Name { get; set; } public List<User> Users { get; private set; } = new List<User>(); public HttpApiServer HttpServer { get; set; } public void Send(Command cmd)
{
cmd.Room = Name;
var frame = HttpServer.CreateDataFrame(cmd);
lock (Users)
{
foreach (var item in Users)
item.Send(frame);
} } public User[] GetOnlines()
{
lock (Users)
return Users.ToArray();
} public void Enter(User user)
{
if (user == null)
return;
if (user.Room != this)
{
user.Room?.Exit(user);
lock (Users)
Users.Add(user);
user.Room = this;
Command quit = new Command { Type = "enter",Message=$"enter room", User = user };
Send(quit);
}
} public void Exit(User user)
{
if (user == null)
return;
lock (Users)
Users.Remove(user);
user.Room = null;
Command quit = new Command { Type = "quit", Message = $"exit room", User = user };
Send(quit);
}
}
房间信息主要包括名称和用户信息,具体行为有进房间,出房间和向房间发送信息。
服务逻辑
有了逻辑信息那就需要把这个信息通过接口的服务方式提供给外部访问操作,接下来定义一个简单的控制器类来描述相关接口服务行为
[BeetleX.FastHttpApi.Controller]
public class Home : BeetleX.FastHttpApi.IController
{
[BeetleX.FastHttpApi.NotAction]
public void Init(HttpApiServer server, string path)
{
for (int i = ; i < ; i++)
{
string key = $"{i:00}";
mRooms[key] = new Room { Name = key, HttpServer = server };
}
server.HttpDisconnect += (o, e) =>
{
GetUser(e.Session)?.Exit();
};
}
private ConcurrentDictionary<string, Room> mRooms
= new ConcurrentDictionary<string, Room>(StringComparer.OrdinalIgnoreCase);
public object Rooms()
{
return from a in mRooms.Values orderby a.Name select new {a.Name};
}
public void Enter(string room, IHttpContext context)
{
User user = GetUser(context.Session);
mRooms.TryGetValue(room, out Room result);
result?.Enter(user);
}
public void Talk(string message, IHttpContext context)
{
if (!string.IsNullOrEmpty(message))
{
var user = GetUser(context.Session);
Command cmd = new Command { Type = "talk", Message = message, User = user };
user?.Room?.Send(cmd);
}
}
public void Login(string name, IHttpContext context)
{
User user = new User();
user.Name = name;
user.Session = context.Session;
user.Address = context.Request.RemoteIPAddress;
SetUser(context.Session, user);
}
private User GetUser(ISession session)
{
return (User)session["__user"];
} private void SetUser(ISession session, User user)
{
session["__user"] = user;
}
}
Init方法
用于初始化房间信息,并绑定连接断开事件,如果用户断开了则执行用户退出房间。
Login方法
登陆到用户中
Rooms方法
获取所有房间信息
Enter方法
用户进入房间
Talk
用户向房间内发送一条消息
启动服务
当功能逻辑写好后,接下来的工作就是让这些接口部署到websocket
服务中,部署的代码比较简单:
class Program
{
static void Main(string[] args)
{
var builder = new HostBuilder()
.ConfigureServices((hostContext, services) =>
{
services.UseBeetlexHttp(o =>
{
o.LogToConsole = true;
o.ManageApiEnabled = false;
o.Port = ;
o.SetDebug();
o.LogLevel = BeetleX.EventArgs.LogType.Warring;
},
typeof(Program).Assembly);
});
builder.Build().Run();
}
}
当服务部署后就可以专心去做前端实现的工作。
Web前端
为了更方便地和Beetlex
服务整合,因此也单独针对性地封装了相应的javascript
组件;除了自有封装的javascript
还涉及到vuejs
的使用。通过以上组件整合前端的代码相比服务端来说就更简单了,详细代码如下:
<body>
<div id="page">
<page-header> </page-header>
<div class="container" style="margin-top:110px;">
<div class="row">
<ul style="list-style:none;">
<li v-for="item in messages" class="message">
<h4>
<span class="label label-success">[{{item.Room}}]</span>
<span class="label label-info">{{item.User.Name}}</span>
<span class="label label-default">{{new Date()}}</span>
</h4>
<div style="padding-left:20px;">
{{item.Message}}
</div>
</li>
</ul>
</div>
</div>
<page-footer :status="loginStatus" @login="onLogin($event)"
@talk="onTalk($event)" @select="onSelectRoom($event)" :rooms="getRooms.result">
</page-footer>
</div>
<script>
beetlex.websocket.receive = function (r) {
page.messages.push(r);
};
beetlex.websocket.disconnect = function () {
page.loginStatus = false;
};
beetlex.useWebsocket();
var login = new beetlexAction("/Login");
var getRooms = new beetlexAction('/Rooms', null, []);
var enterRoom = new beetlexAction('/Enter');
var talk = new beetlexAction('/Talk');
login.requested = function (r) {
page.loginStatus = true;
};
var model = {
getRooms: getRooms,
loginStatus: false,
login: login,
talk: talk,
enterRoom: enterRoom,
messages: [],
};
var page = new Vue({
el: '#page',
data: model,
methods: {
onSelectRoom: function (r) {
// alert(r);
this.enterRoom.post({ room: r });
},
onLogin: function (r) {
this.login.post({ name: r });
},
onTalk: function (msg) {
talk.post({ message: msg });
},
},
});
getRooms.get();
</script>
</body>
beetlex
是针对http
和websocket
封装的功能类,它自动兼容这两种请求;在默认情况是http
请求,调用useWebsocket
后所有请求都优先使用websocket
;当websocket
不可用的情况组会自动切回到http
.
beetlexAction
用于描述一个请求,分别提供了post
和get
方法;当在websocket
下这两个方法的处理方式一样。
运行效果
演示地址
代码地址
https://github.com/IKende/BeetleX-Samples/tree/master/WebSocket.Chat
BeetleX之快速构建Web多房间聊天室的更多相关文章
- SignalR 实现Web多人聊天室
ASP .NET SignalR 是一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信.什么是实时通信的Web呢?就是让客户端(Web页面)和服务器端可以互相通知消 ...
- UIkit – 轻量级前端框架,帮助你快速构建 Web 界面
UIKit 是一个轻量级,模块化的前端框架,用于构建快速和强大的 Web 界面.UIKit 为您提供了 HTML,CSS 和 JavaScirpt 组件,使用简单,容易定制和扩展.UIKit 基于 L ...
- Mysql EF Core 快速构建 Web Api
(1)首先创建一个.net core web api web项目; (2)因为我们使用的是ef连接mysql数据库,通过NuGet安装MySql.Data.EntityFrameworkCore,以来 ...
- SpringBoot 快速构建微服务体系 知识点总结
可以通过http://start.spring.io/构建一个SpringBoot的脚手架项目 一.微服务 1.SpringBoot是一个可使用Java构建微服务的微框架. 2.微服务就是要倡导大家尽 ...
- ASP.NET SignalR 与LayIM配合,轻松实现网站客服聊天室(四) 添加表情、群聊功能
休息了两天,还是决定把这个尾巴给收了.本篇是最后一篇,也算是草草收尾吧.今天要加上表情功能和群聊.基本上就差不多了,其他功能,读者可以自行扩展或者优化.至于我写的代码方面,自己也没去重构.好的,我们开 ...
- websocket 多聊天室功能
websocket 类也是在网上找到的. 修改后可以用来创建多房间聊天室.可以发送图片表情,图片,及文字. 分享的代码,已经测试.可正常运行 HTML 端代码 <!DOCTYPE html> ...
- 使用轮询&长轮询实现网页聊天室
前言 如果有一个需求,让你构建一个网络的聊天室,你会怎么解决? 首先,对于HTTP请求来说,Server端总是处于被动的一方,即只能由Browser发送请求,Server才能够被动回应. 也就是说,如 ...
- 使用ASP.NET 构建 Web 应用程序快速入门-8小时的免费培训视频
- Scott Hanselman的中文博客[转载] [原文发表地址] Building Web Apps with ASP.NET Jump Start - 8 Hours of FREE Trai ...
- .net core下使用FastHttpApi构建web聊天室
一般在dotnet core下构建使用web服务应用都使用asp.net core,但通过FastHttpApi组建也可以方便地构建web服务应用,在FastHttpApi功能的支持下构建多人聊天室是 ...
随机推荐
- Android MediaPlayer 在 STREAM_ALARM 中播放媒体
最近因为公司需求,要实现后台播放音频,同时广告机中的视频因为客户需求调至静音,不能通过修改系统的媒体音量来让音频发声. private MediaPlayer mediaPlayer; private ...
- Lua 截取字符串(截取utf-8格式字符串)
对utf-8完全没概念的可以看看我上一篇随笔:简单说说utf-8编码格式 另外,还要知道string.sub 和 string.byte 的用法. 先上完整代码: local StringHelper ...
- Java源码 HashMap<K,V>
HashMap类 https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html public class HashMap<K, ...
- 文件名后面加(1).text
; //在重复名称后加(序号) while (File.Exists(path)) { if (path.Contains(").")) { int start = path.La ...
- ubuntu 网卡名称重命名
ubuntu 网卡名称重命名 参考:https://blog.csdn.net/hzj_001/article/details/81587824 biosdevname 和 net.ifnames 两 ...
- 浅读vue-router源码,了解vue-router基本原理
项目中使用vue-router的时候,会进行以下操作(可能具体不是这么写的,但是原理一样): 定义映射关系routes: 定义router实例的时候传入vue和参数{routes...}: 定义vue ...
- scala 面向对象之 继承
scala 面向对象之 继承 scala 1.extends Scala中,让子类继承父类,与Java一样,也是使用extends关键字 继承就代表,子类可以从父类继承父类的field和metho ...
- 如何将编译后的文件打包成jar文件
如果需要修改像spring和dubbo中的jar包源码,修改后怎么打包呢? 如下: 1.win+r进入命令行: 2.找到需要打包的class文件: 3.jar -cvf [jar包的名字] [需要打包 ...
- dom和bom之间的区别
BOM的核心是windows,表示的是一个浏览器的实例,在网页中自定义的任何一个对象.变量和函数,都以windows作为其全局对象 DOM是针对HTML和XML文档的一个API bom:(Browse ...
- 前端imageBuffer设置图片src(后端返回二进制流图片)
参考地址1:前端imageBuffer设置图片src(后端到前端直传buffer) 参考地址2:axios根据流生成图片 本质为buffer转base64 // 获取项目截图 getItemPic() ...