其实构建一个Web多房间聊天室也并不是什么困难的技术,借助于websocket就可以轻松实现多用户在线实时通讯交互;在这里主要介绍一下在BeetleXBeetleXjs的支持下如何让这个功能实现的更简单和高效。接下来通过使用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

是针对httpwebsocket封装的功能类,它自动兼容这两种请求;在默认情况是http请求,调用useWebsocket后所有请求都优先使用websocket;当websocket不可用的情况组会自动切回到http.

beetlexAction

用于描述一个请求,分别提供了postget方法;当在websocket下这两个方法的处理方式一样。

运行效果

演示地址

http://chat.ikende.com

代码地址

https://github.com/IKende/BeetleX-Samples/tree/master/WebSocket.Chat

BeetleX之快速构建Web多房间聊天室的更多相关文章

  1. SignalR 实现Web多人聊天室

      ASP .NET SignalR 是一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信.什么是实时通信的Web呢?就是让客户端(Web页面)和服务器端可以互相通知消 ...

  2. UIkit – 轻量级前端框架,帮助你快速构建 Web 界面

    UIKit 是一个轻量级,模块化的前端框架,用于构建快速和强大的 Web 界面.UIKit 为您提供了 HTML,CSS 和 JavaScirpt 组件,使用简单,容易定制和扩展.UIKit 基于 L ...

  3. Mysql EF Core 快速构建 Web Api

    (1)首先创建一个.net core web api web项目; (2)因为我们使用的是ef连接mysql数据库,通过NuGet安装MySql.Data.EntityFrameworkCore,以来 ...

  4. SpringBoot 快速构建微服务体系 知识点总结

    可以通过http://start.spring.io/构建一个SpringBoot的脚手架项目 一.微服务 1.SpringBoot是一个可使用Java构建微服务的微框架. 2.微服务就是要倡导大家尽 ...

  5. ASP.NET SignalR 与LayIM配合,轻松实现网站客服聊天室(四) 添加表情、群聊功能

    休息了两天,还是决定把这个尾巴给收了.本篇是最后一篇,也算是草草收尾吧.今天要加上表情功能和群聊.基本上就差不多了,其他功能,读者可以自行扩展或者优化.至于我写的代码方面,自己也没去重构.好的,我们开 ...

  6. websocket 多聊天室功能

    websocket 类也是在网上找到的. 修改后可以用来创建多房间聊天室.可以发送图片表情,图片,及文字. 分享的代码,已经测试.可正常运行 HTML 端代码 <!DOCTYPE html> ...

  7. 使用轮询&长轮询实现网页聊天室

    前言 如果有一个需求,让你构建一个网络的聊天室,你会怎么解决? 首先,对于HTTP请求来说,Server端总是处于被动的一方,即只能由Browser发送请求,Server才能够被动回应. 也就是说,如 ...

  8. 使用ASP.NET 构建 Web 应用程序快速入门-8小时的免费培训视频

    - Scott Hanselman的中文博客[转载] [原文发表地址] Building Web Apps with ASP.NET Jump Start - 8 Hours of FREE Trai ...

  9. .net core下使用FastHttpApi构建web聊天室

    一般在dotnet core下构建使用web服务应用都使用asp.net core,但通过FastHttpApi组建也可以方便地构建web服务应用,在FastHttpApi功能的支持下构建多人聊天室是 ...

随机推荐

  1. O056、Extend Volume 操作

    参考https://www.cnblogs.com/CloudMan6/p/5645305.html   今天学习如何扩大volume的容量,为了保护现有的数据,cinder不允许缩小volume. ...

  2. sccrapy 爬虫框架网数据库储存时去重的问题

    from scrapy.exceptions import DropItem #导入异常处理模块 class Baidu03Pipeline(object): def __init__(self): ...

  3. CSS3--transform相关属性

    ---transform属性使用--- 1.过度时间 :transition: transform 2s; 2.transform: 应用 2D 或 3D 转换.可以对元素进行旋转.缩放.移动或倾斜. ...

  4. init是一个自定义方法名

    init是一个自定义方法名,用于初始化页面变量.上面的代码表示初始化方法是在当前网页加载后执行的(当浏览器打开网页时,触发窗口对象的onload方法,用上面的代码执行名为init的初始化方法).事实上 ...

  5. 密码基础知识(2)以RSA为例说明加密、解密、签名、验签

    密码基础知识(1)https://www.cnblogs.com/xdyixia/p/11528572.html 一.RSA加密简介 RSA加密是一种非对称加密.是由一对密钥来进行加解密的过程,分别称 ...

  6. mybatis sql语句中 in() 长度为0或null的情况

    mybatis sql语句中 in() 长度为0或null的情况 比如: select * from A where colName IN <foreach collection="m ...

  7. SmartBinding与kbmMW#3

    前言 在SmartBinding #2中,我介绍了新的自动绑定功能,支持在Form设计器中直接定义绑定.不仅如此,kbmMW SmartBind还有更多很酷的功能,即将发布的kbmMW中的SmartB ...

  8. Java注解【一、概述】

    前面几篇Java学习笔记都是半夜写的,比较伤身体,今天开始想调整生物钟,早上起来学2小时,看看能坚持多久 本周目标: 1.JavaJDBC使用 2.JavaWeb编程 3.Java框架基础(反射+注解 ...

  9. zookeeper--为分布式应用提供协调服务

    1.概述 zookeeper是一个开源的.分布式的.为分布式应用提供协调服务的Apache项目 zookeeper的工作机制 zookeeper从设计模式角度来理解:是一个基于观察者模式设计的分布式服 ...

  10. [ZOJ 3063] Draw Something Cheat

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4706 思路:字符串是一个集合(由0到多个A~Z字符组成),我们可以假 ...