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

信息逻辑

既然是多房间聊天室那它具备两个主要元素,分别是用户和房间;下面通过类来描述这两个元素:

用户

  1. public class User
  2. {
  3. public string Name { get; set; }
  4.  
  5. public string Address { get; set; }
  6.  
  7. [JsonIgnore]
  8. public ISession Session { get; set; }
  9.  
  10. [JsonIgnore]
  11. public Room Room { get; set; }
  12.  
  13. public void Send(BeetleX.FastHttpApi.WebSockets.DataFrame frame)
  14. {
  15. frame.Send(Session);
  16. }
  17.  
  18. public void Exit()
  19. {
  20. Room?.Exit(this);
  21. }
  22. }

信息描述比较简单主要包括信息用:名称,会话和房间;涉及的行为有发送信息和退出房间。

房间

  1. public class Room
  2. {
  3.  
  4. public string Name { get; set; }
  5.  
  6. public List<User> Users { get; private set; } = new List<User>();
  7.  
  8. public HttpApiServer HttpServer { get; set; }
  9.  
  10. public void Send(Command cmd)
  11. {
  12. cmd.Room = Name;
  13. var frame = HttpServer.CreateDataFrame(cmd);
  14. lock (Users)
  15. {
  16. foreach (var item in Users)
  17. item.Send(frame);
  18. }
  19.  
  20. }
  21.  
  22. public User[] GetOnlines()
  23. {
  24. lock (Users)
  25. return Users.ToArray();
  26. }
  27.  
  28. public void Enter(User user)
  29. {
  30. if (user == null)
  31. return;
  32. if (user.Room != this)
  33. {
  34. user.Room?.Exit(user);
  35. lock (Users)
  36. Users.Add(user);
  37. user.Room = this;
  38. Command quit = new Command { Type = "enter",Message=$"enter room", User = user };
  39. Send(quit);
  40. }
  41. }
  42.  
  43. public void Exit(User user)
  44. {
  45. if (user == null)
  46. return;
  47. lock (Users)
  48. Users.Remove(user);
  49. user.Room = null;
  50. Command quit = new Command { Type = "quit", Message = $"exit room", User = user };
  51. Send(quit);
  52. }
  53. }

房间信息主要包括名称和用户信息,具体行为有进房间,出房间和向房间发送信息。

服务逻辑

有了逻辑信息那就需要把这个信息通过接口的服务方式提供给外部访问操作,接下来定义一个简单的控制器类来描述相关接口服务行为

  1. [BeetleX.FastHttpApi.Controller]
  2. public class Home : BeetleX.FastHttpApi.IController
  3. {
  4. [BeetleX.FastHttpApi.NotAction]
  5. public void Init(HttpApiServer server, string path)
  6. {
  7. for (int i = ; i < ; i++)
  8. {
  9. string key = $"{i:00}";
  10. mRooms[key] = new Room { Name = key, HttpServer = server };
  11. }
  12. server.HttpDisconnect += (o, e) =>
  13. {
  14. GetUser(e.Session)?.Exit();
  15. };
  16. }
  17. private ConcurrentDictionary<string, Room> mRooms
  18. = new ConcurrentDictionary<string, Room>(StringComparer.OrdinalIgnoreCase);
  19. public object Rooms()
  20. {
  21. return from a in mRooms.Values orderby a.Name select new {a.Name};
  22. }
  23. public void Enter(string room, IHttpContext context)
  24. {
  25. User user = GetUser(context.Session);
  26. mRooms.TryGetValue(room, out Room result);
  27. result?.Enter(user);
  28. }
  29. public void Talk(string message, IHttpContext context)
  30. {
  31. if (!string.IsNullOrEmpty(message))
  32. {
  33. var user = GetUser(context.Session);
  34. Command cmd = new Command { Type = "talk", Message = message, User = user };
  35. user?.Room?.Send(cmd);
  36. }
  37. }
  38. public void Login(string name, IHttpContext context)
  39. {
  40. User user = new User();
  41. user.Name = name;
  42. user.Session = context.Session;
  43. user.Address = context.Request.RemoteIPAddress;
  44. SetUser(context.Session, user);
  45. }
  46. private User GetUser(ISession session)
  47. {
  48. return (User)session["__user"];
  49. }
  50.  
  51. private void SetUser(ISession session, User user)
  52. {
  53. session["__user"] = user;
  54. }
  55. }

Init方法

用于初始化房间信息,并绑定连接断开事件,如果用户断开了则执行用户退出房间。

Login方法

登陆到用户中

Rooms方法

获取所有房间信息

Enter方法

用户进入房间

Talk

用户向房间内发送一条消息

启动服务

当功能逻辑写好后,接下来的工作就是让这些接口部署到websocket服务中,部署的代码比较简单:

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. var builder = new HostBuilder()
  6. .ConfigureServices((hostContext, services) =>
  7. {
  8. services.UseBeetlexHttp(o =>
  9. {
  10. o.LogToConsole = true;
  11. o.ManageApiEnabled = false;
  12. o.Port = ;
  13. o.SetDebug();
  14. o.LogLevel = BeetleX.EventArgs.LogType.Warring;
  15. },
  16. typeof(Program).Assembly);
  17. });
  18. builder.Build().Run();
  19. }
  20. }

当服务部署后就可以专心去做前端实现的工作。

Web前端

为了更方便地和Beetlex服务整合,因此也单独针对性地封装了相应的javascript组件;除了自有封装的javascript还涉及到vuejs的使用。通过以上组件整合前端的代码相比服务端来说就更简单了,详细代码如下:

  1. <body>
  2. <div id="page">
  3. <page-header> </page-header>
  4. <div class="container" style="margin-top:110px;">
  5. <div class="row">
  6. <ul style="list-style:none;">
  7. <li v-for="item in messages" class="message">
  8. <h4>
  9. <span class="label label-success">[{{item.Room}}]</span>
  10. <span class="label label-info">{{item.User.Name}}</span>
  11. <span class="label label-default">{{new Date()}}</span>
  12. </h4>
  13. <div style="padding-left:20px;">
  14. {{item.Message}}
  15. </div>
  16. </li>
  17. </ul>
  18. </div>
  19. </div>
  20. <page-footer :status="loginStatus" @login="onLogin($event)"
  21. @talk="onTalk($event)" @select="onSelectRoom($event)" :rooms="getRooms.result">
  22. </page-footer>
  23. </div>
  24. <script>
  25. beetlex.websocket.receive = function (r) {
  26. page.messages.push(r);
  27. };
  28. beetlex.websocket.disconnect = function () {
  29. page.loginStatus = false;
  30. };
  31. beetlex.useWebsocket();
  32. var login = new beetlexAction("/Login");
  33. var getRooms = new beetlexAction('/Rooms', null, []);
  34. var enterRoom = new beetlexAction('/Enter');
  35. var talk = new beetlexAction('/Talk');
  36. login.requested = function (r) {
  37. page.loginStatus = true;
  38. };
  39. var model = {
  40. getRooms: getRooms,
  41. loginStatus: false,
  42. login: login,
  43. talk: talk,
  44. enterRoom: enterRoom,
  45. messages: [],
  46. };
  47. var page = new Vue({
  48. el: '#page',
  49. data: model,
  50. methods: {
  51. onSelectRoom: function (r) {
  52. // alert(r);
  53. this.enterRoom.post({ room: r });
  54. },
  55. onLogin: function (r) {
  56. this.login.post({ name: r });
  57. },
  58. onTalk: function (msg) {
  59. talk.post({ message: msg });
  60. },
  61. },
  62. });
  63. getRooms.get();
  64. </script>
  65. </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. 【原创】大叔经验分享(58)kudu写入压力大时报错

    kudu写入压力大时报错 19/05/18 16:53:12 INFO AsyncKuduClient: Invalidating location fd52e4f930bc45458a8f29ed1 ...

  2. vue 登录 + 记住密码 + 密码加密解密

    <template> <el-form :model="ruleForm"> <h3 class="title">系统登录& ...

  3. python3中OS模块

    os模块 OS模块简单的来说它是一个Python的系统编程的操作模块,可以处理文件和目录这些我们日常手动需要做的操作. 可以查看OS模块的帮助文档: import os:#导入os模块 help(os ...

  4. flex整页布局

    使用flex进行整页的三列布局,flex:1下的子元素无法铺满父级.给flex:1元素,添加stretch拉伸 display: flex; align-content: stretch; align ...

  5. 平时工作常用linux命令总结

    mkdir 创建目录  make dir cp 拷贝文件  copy mv 移动文件   move rm  删除文件 remove # 创建连级目录 mkdir -p a/b/c # 拷贝文件夹a到文 ...

  6. Gitlab创建ssh key并添加配置

    1 生成ssh key  zj改成你自己的邮箱或者名字之类的 ssh-keygen -t rsa -C "zj" 2 找到你生成的ssh key copy 公钥 添加到gitlab ...

  7. xtrabackup的使用

    Percona-xtrabackup是 Percona公司开发的一个用于MySQL数据库物理热备的备份工具. 一.安装xtrabackup 采用rpm包的方式进行安装 [root@server- ~] ...

  8. gulp connect.static is not a function

    npm install --save serve-static var serveStatic = require('serve-static');

  9. Oracle中常见表与各类结构的查询

    ----------------------------------------------------------------------用户--查询:当前用户的缺省表空间select userna ...

  10. 使用curl出现,curl: /usr/local/lib/libssl.so.1.1: version `OPENSSL_1_1_1' not found (required by /usr/lib/x86_64-linux-gnu/libcurl.so.4)

    主要原因是curl找不到openssl的路径,所以只要将openssl的路径添加到相应的变量中就可以了. 参考连接https://blog.csdn.net/RookieWutongshu/artic ...