liwa233/ChatWindow:本次系统我选择了基于C/S架构的聊天室系统,一是因为C/S作为一个基础性架构,应用广泛,可以很好增强架构设计能力,二是因为之前做过类似系统,可以对其进行重构,增加新功能,认识到架构优化的重要意义。ChatWindowWRITE

本程序为基于C/S的网络聊天室系统,使用Linux网络编程作为服务器,使用QT编程作为客户端。

客户端通过输入IP地址、端口号、Email、聊天名称、聊天组号连接到服务器,用户通过客户端发送消息,同时接收来自相同组其他客户端发送的消息,获取当前在线用户信息,通知新用户的上线和用户的下线,实现群聊功能。

服务器负责管理用户的连接、发送消息与退出,有新用户建立连接时,记录新用户信息,并向同组其他客户端广播;用户退出时,清除用户信息,并向同组其他客户端广播离开信息;当有用户发送消息时,向同组其他客户端广播。

服务器主要功能有:管理连接的客户端、接收客户端发送数据、向客户端转发数据、向客户端发送数据。

用例图如下所示:

图1服务器用例图

服务器接收客户端数据时序图如下所示:

图3服务器接收客户端数据时序图

服务器非功能需求

高性能

作为C/S架构的聊天程序,首要解决高并发需求,服务器可以同时相应多个客户端,并且不会因为某个客户端而阻塞,具有较高的吞吐量和较低的相应时延,满足实时聊天的需求。

此系统需要选取合适的网络开发模型,网络IO模型,可以满足高并发高性能需求,代码实现方面,需选择高效的数据结构与算法,对系统性能进行全面提升。

可修改性可读性代码实现方面应满足可修改性与可读性,便于以后进行维护及扩展。

系统应满足可读性,代码风格统一,符合编程语言规范,符合编程语言惯用法,命名规范、明了易懂,文档齐全,具有良好的注释,代码结构规整,逻辑清晰,符合“高内聚-低耦合”原则。

系统应满足模块化,系统应是多个模块组合,每个模块具有较高的内聚性,每个模块都便于测试,模块间应具有较低的耦合。

系统应满足可重用性,对于公共的函数、模块、组件将其提出出来进行封装,供未来的重用,节省开发成本,提高开发效率。

系统应满足可维护性,可以高效的对系统进行更改、升级。

可测试性

可以较为简便的对系统进行测试,快速暴露于发现系统的错误,并进行修改。

容易编写桩程序替换底层模块(如数据库等)进行测试。

可以方便的进行白盒测试、黑盒测试、性能测试、安全性测试等。

可扩展性

系统能够满足相应的纵向扩展与横向扩展。

可以通过在一个计算节点中增加资源或更好利用资源进行纵向扩展,如选择合适的并发方式与模型、满足高性能等。

可以通过增加更能多的计算节点进行扩展,如将长连接与短连接分布在不同服务器上,将数据库分离开来,使用RPC进行扩展等。

客户端可跨平台,可方便修改通信协议,增加新功能。

客户端功能需求

客户端用例图如下所示:

图4客户端用例图

事件流:

备选流:

前置条件:

后置条件:

进入到聊天界面进行操作

接收消息用例文本:

若JSON数据解析失败,用例结束

客户端成功连接服务器

客户端可跨平台,可方便进行功能扩充。

架构

服务器初始架构

如下图所示,整体为C/S架构,多个客户端与服务器通信,所有客户端仅依赖一个服务器,聊天服务器承担责任过重,具有较大的性能压力。

通信协议采用字符串拼接形式,形如code:name:data,优点是简单,体积小,缺点是可读性差、扩展性差,若需要增加新字段,需要大量修改程序。

图5服务器初始架构

网络通信采用原始的selectI/O多路复用方式,虽较好解决了并发性问题,但实现起来较为臃肿,且与业务代码耦合严重,难以修改维护。

图5服务器初始代码结构

代码没有清晰的模块,一个文件承载了过多功能,没有较多体现分而治之思想,且代码存在注释缺失,对可修改可读性造成了更大的损害。

优化后服务器架构

图6当前服务器架构

支持多种客户端,客户端与服务器使用TCP长连接进行消息推送,获取数据信息时使用TCP短连接,降低性能压力,TCP长连接可和TCP短连接分离为不同服务器,TCP短连接使用HTTP协议,进行横向扩展。

客户端与服务器使用JSON格式传输数据,方便扩展,如可以容易的进行客户端跨平台扩展,增加修改JSON格式字段可很少或不修改现有代码,增加新功能。

数据库使用redis内存数据库,具有很高的性能,用于存储各聊天室基本信息,聊天数据(使用过期策略清理聊天数据),且可独立为一高性能服务器,提供高效的数据访问能力。

网络连接层次使用基于IO多路复用、Reactor模式的异步事件处理库—Libevent.

也即将网络连接层更改为事件驱动架构,Libevent提供一个主事件循环,监听网络IO等事件,在检测到事件时触发具有特定参数的回调函数。通过事件驱动,将网络IO操作与业务层可以较好的解耦。

此外,使用现成的成熟的网络库,可以提高开发效率,提高网络并发性能,编写系统时可专注于业务代码,代码更易于维护、修改。

图7服务器采用分层架构

接入层:使用libevent事件驱动机制,负责管理与客户端的长连接,接收来自客户端数据,向各客户端发送数据。此层保存接入层客户端的标识符sockfd和业务层客户端标识符email的映射,使得下层不用考虑接入层的特有数据。

业务层:根据接入层传来的email和信息,解析JSON,处理具体的业务,对于群聊业务来说,根据emial所在的groupid将消息转发给相应组员。上层接入层通过接口返回值处理相应的接入层操作。

DAO层:用于访问redis数据库,进行具体的数据库访问操作,向上层返回数据访问接口。

redis数据库层:存储用户会话信息,此系统中暂时使用内存中的map代替,体现了分层的好处—可测试性,基本数据结构为:

Key:email,Value:[email,name,groupid]客户端架构

QT提供了一些设计优秀的结构、行为机制,可以使程序具有良好的架构。如QT将界面与业务逻辑相分离,可以独立方便修改界面与业务逻辑,而不用做过多修改;使用信号/槽机制来完成组件间的通信,是事件驱动编程的一种独特实现方式,很好的解除了各个组件间的耦合,使得客户端开发与维护变得简单。

客户端发向服务器:

服务器发向客户端:

代码

服务器—接入层

接入客户端类定义如下所示,对于能使用const的场合,均使用const修饰,作为一种安全保证和标识。传递函数参数时,尽量使用引用,而不是值拷贝,可以得到较好的效率。使用容器时使用STL模板容器,拥有很好的性能,特别是使用map极大加快了查询的速度。

因为网络库使用了基于C语言的Libevent库,因此需要将面向过程的LibeventAPI与面向对象的类结合起来。

使用命名空间来管理类,增加系统的模块化。

务层设置),之后将数据转交给业务层,此次通过引用来是业务层修改数据,业务层处理后返回:处理的是什么类型的数据、应发送给原发送方的数据、应转发给相应用户的数据。接入层再根据返回值调用相应处理函数,进行数据转发等操作。

此处使用了C++11语法—auto关键字,可自动推断变量类型。对于多重条件,使用switch,更加清晰地处理各种情况。程序中未显示出现数字,即魔数,均使用常量来代替。

服务层接口如下所示,仅向上层—接入层提供两个接口,其中data_dispatch接口承担了多个相似功能,首先传入上层发送方的email和接收到的数据,再解析数据,根据数据格式进行相应处理,如果需要返回给上层发送方、多个接收者,则修改引用的参数即可。offline接口负责用户下线的处理。

此接口类使用了虚析构函数,使用实现dao接口的对象来操纵数据库。此外,使用conststatic定义了大量常量便于使用。

业务层具体实现类面向接口编程,满足设计模式中合成复用原则—细节应依赖抽象,抽象不应依赖细节。

DAO层用于与数据库交互,接口如下所示,接口设计使用了C++纯虚函数语法,符合语言规范。

namespacedao{classIOnlineUserInfoDao{public:virtualvoidadd_new_user(std::stringemail,std::stringname,intgroupid)=0;virtualbooldel_user_by_email(std::stringemail)=0;virtualstd::vectorquery_emails_by_groupid(intgroupid)=0;virtualintcheck_email_exists(std::stringemail)=0;virtualboolexclude_email_from_vector(std::vector&emails,std::stringexcluded_email)=0;virtualboolquery_clientinfo_by_email(std::stringemail,dao::ClientInfo&client_info)=0;virtualstd::vectorquery_clientsinfo_by_groupid(intgroupid)=0;virtualvoidprint_map_clients_info()=0;virtual~IOnlineUserInfoDao()=default;以下三段代码分别为添加新用户、按照email删除用户、按照groupid(聊天组id)查询所有用户。

voidOnlineUserInfoDaoImpl::add_new_user(std::stringemail,std::stringname,intgroupid){ClientInfoc;email=email;name=name;groupid=groupid;map_clients_info[email]=c;}boolOnlineUserInfoDaoImpl::del_user_by_email(std::stringemail){autoit=map_clients_info.find(email);if(it!=map_clients_info.end()){map_clients_info.erase(it);returntrue;}returnfalse;std::vectorOnlineUserInfoDaoImpl::query_emails_by_groupid(intgroupid){std::vectoremails;for(auto&it:map_clients_info){if(it.second.groupid==groupid)emails.push_back(it.second.email);}returnemails;服务器—工具类

下面为解析客户端发来JSON数据的类的构造函数,传入JSON数据,将字段数组存在成员变量中。解析JSON库时使用rapidjson开源JSON解析库。

以下为ChatTcpSocket类的两个函数,startRecvMsg函数用于连接接收到数据时的信号,接收到信号时调用transferMsg函数,此时transferMsg再发送接收到数据的信号。

//开始接收消息voidChatTcpSocket::startRecvMsg(){connect(&socket,&QTcpSocket::readyRead,this,&ChatTcpSocket::transferMsg);}//接收到消息时发送信号voidChatTcpSocket::transferMsg(){QByteArraynetdata=socket.readLine();emitrecvMsg(QString(netdata));以下为聊天窗口类ChatWindow的槽函数,当ChatTcpSocket类接收到数据并调用transferMsg发送后,ChatWindow中的recvMsg函数进行接收处理。解析服务器发送来的JSON数据,根据不同CODE字段调用不同处理函数进行处理。

voidChatWindow::recvMsg(constQString&data){serverjson::ParseServerJsonp(data);switch(p.getCode()){caseserverjson::USER_ONLINE_CODE:newUserOnline(p.getEmail(),p.getName());break;caseserverjson::USER_OFFLINE_CODE:if(membersMap.contains(p.getEmail())){userOffline(p.getEmail(),membersMap[p.getEmail()]);}break;caseserverjson::USER_MSG_CODE:if(membersMap.contains(p.getEmail())){newUserMsg(p.getEmail(),membersMap[p.getEmail()],getMsg(),p.getTime());break;caseserverjson::GROUP_MEMBER_LIST_CODE:disGroupMembersList(p.getMembers());break;}以下为客户端发送在线信息和聊天信息函数,将数据封装为JSON数据进行发送。//发送上线信息

voidChatTcpSocket::sendOnline(){clientjson::Onlineon(clientjson::ONLINE_CODE,email,name,groupid);sendMsgToServer(on.toJson());}//用户发送信息voidChatTcpSocket::sendMsg(constQString&email,constQString&msg){clientjson::SendMsgm(clientjson::SENDMSG_CODE,email,msg);sendMsgToServer(m.toJson());}质量评价高性能

此系统中,使用C语言的网络库Libevent,为轻量级、基于异步事件驱动的开源高性能网络库。底层使用主流的并发解决方案—I/O多路复用。因此借助Libevent库可以实现高并发能力的C/S程序。实际测试中本系统具有较好的并发能力,允许多个客户端向服务器同时发送消息,并且具有较低的时延与响应速度。

代码层面,使用高效的算法和数据结构,如在进行大量查询操作时,使用map数据结构替换vector等线性结构。

数据库使用基于内存的Redis数据库存储在线用户信息,Redis数据库具有优秀的性能表现。

可读可修改性

系统具有一定的可读性,代码风格统一,符合编程语言规范,符合编程语言惯用法。对函数、类、模块、文件的命名较为规范,力求明了易懂。对函数、代码关键部分均添加了注释,代码结构规整,逻辑清晰,遵从“高内聚—低耦合原则”。

架构上使用分层,每一层实现较为清晰,相对独立,向上层提供接口,带来了良好的可读与可修改性。

系统使用模块化设计,使用C++的命名空间将类分为各个不同模块。每个模块具有较高的内聚性,便于修改与测试,模块间具有较低的耦合性。

系统尽可能将公共函数、模块提取出来进行封装,以供重用,节省开发成本,提升开发效率。

系统使用标准的分层架构,带来了良好的可测试性。因为各层间通过接口来调用,可以单独测试每一层的接口。而且对于下层模块,可以通过桩程序代替测试,本系统中为测试高层模块,将最底层的数据库使用map变量代替,不用修改高层模块,即完成了高层模块的测试,具有较好的可测试性。

系统使用异步技术来支持,具有良好的性能,也即支持良好的垂直扩展,可以通过在一个计算节点中增加资源或更好利用资源进行纵向扩展。

系统可将长连接与短连接分离在不同服务器,短连接使用HTTP协议,因为采用了分层结构,数据库也可以较为容易进行分离,满足水平扩展。

本系统设计过程中,以设计模式基本思想为指导,如使用接口满足开闭原则和依赖倒转原则,每个类满足单一职责原则,满足高内聚—低耦合原则。设计接口时,尽可能满足接口隔离原则。

本次系统我选择了基于C/S架构的聊天室系统,一是因为C/S作为一个基础性架构,应用广泛,可以很好增强架构设计能力,二是因为之前做过类似系统,可以对其进行重构,增加新功能,认识到架构优化的重要意义。

优化过程中,我深切感受到了一个设计良好的架构带来的诸多好处。

面对着当初设计不友好的代码,借助于软件体系结构这门课程所学的架构知识,我开始重新设计并编写聊天室系统。在众多的架构模式中,我综合选择了最为基础性架构—分层架构,掌握好分层架构才能灵活运用其他架构模式。我参照最著名的分层设计TCP/IP协议,尝试着将我的系统分为四个层次—接入层、服务层、DAO层、数据库。每一层次向上层提供相应的接口,每一层次相对独立,只为紧接着上层服务,使用紧邻的下层提供的服务,而且不存在跨层次调用。这样,整个系统就有了大体上较为清晰的结构,我也体会到了分层带来的好处:当编写、修改某一功能时,我可以专注与该功能所在层次,而不用过多修改其他层次,更不会出现之前牵一发而动全身的现象;当我在进行测试时,我也要使用桩程序,替换掉某一层,单独测试某一层,如我使用内存中的map数据结构替换掉redis数据库,程序也具有相同的效果。

总之,未来在设计系统时,要充分考虑架构思想,设计模式思想,不断在实践中增强自己的架构运用能力。

THE END
1.聊天的翻译是:Chat中文翻译英文意思,翻译英语a亲爱的,你去哪里了 Dear, where did you go to[translate] a请不要担心我我们的爱是永恒的 Please do not have to worry my our love is eternal[translate] a经常听磁带 Listens to the magnetic tape frequently[translate] a如果 If[translate] a聊天 Chat[translate]http://eyu.zaixian-fanyi.com/fan_yi_7055
2.探秘开源聊天应用:Chat群组聊天- 支持创建多个群组,方便团队协作。 文件分享- 用户可以便捷地上传并分享各种类型的文件。 自定义部署- 开源特性允许你根据需求在自己的服务器上部署,保护数据隐私。 API 扩展- 提供API接口,便于与其他系统集成或扩展功能。 使用场景 小团队沟通- Chat 可以作为一个简单易用的内部沟通工具,替代邮件等传统沟通https://blog.csdn.net/gitblog_00030/article/details/137134682
3.chat是什么意思用法chat的用法: chat的用法1:chat的基本意思是轻松、无拘无束地、愉快地、语流松散地、不假思索地谈话,一般作“聊天,闲谈”解。 chat的用法2:chat只用作不及物动词,“闲谈”的内容常由介词about引出,“闲谈”的对方常用介词to或with引出。 chat的用法3:chat与over连用,表示“一边…一边聊天”。 chat的英语例句 https://wap.zol.com.cn/ask/details_15987086_5318342_3.html
4.前哈工大教授开发的ChatALL火了!可同时提问17个聊天模型,ChatGPT/Bing有人开发了一个名叫“ChatALL”的应用,可以将你的提问同时发送给10多个市面上常见的聊天机器人,比如ChatGPT、GPT4、Bing、Bard、Claude、文心一言、讯飞星火等等,并一一展现出来。 由此一来,你就可以轻松比对出答得最好的那一个,然后采用。 简直太方便了有没有? https://zhuanlan.zhihu.com/p/630026195
5.聊天泡泡(chatbubble)图片png,ico,icns图标爱给网提供海量的图标库资源素材免费下载, 本次作品为png,ico,icns 格式的聊天泡泡(chat bubble), 本站编号42046601, 该图标库素材大小为14k, 该素材已被下载:19次,许可范围为可商用,协议名称为ffcu协议, 更多精彩图标库素材,尽在爱给网。 浏览本次作品的您可能还对 网络图标气泡闲聊 感兴趣。 该https://www.aigei.com/item/chat_bubble_li_10.html
6.聊天室/chatroom17岁的青年威廉(阿隆·强森 Aaron Johnson 饰)在网上建立了一个聊天室,此后不久,伊娃(伊莫珍·波茨 Imogen Poots 饰)、吉姆(马休·比尔德 Matthew Beard 饰)、艾米莉(汉娜·莫瑞 Hannah Murray 饰)、莫(丹尼尔·卡鲁亚 Daniel Kaluuya 饰)这几个分处不同地方、彼此陌生的年轻人相继聚集于此。他们畅谈心事,尽情https://movie.douban.com/subject/3279065/
7.ChatAA基于GPT3.5和GPT4.0接口开发的聊天网站标签:聊天对话AI对话AI聊天ChatAA 链接直达手机查看 ChatAA是一款基于GPT3.5和GPT4.0接口开发的聊天网站,旨在为用户提供高效便捷的沟通体验。它具备基础问答功能、智能体功能、绘图(包括dalle-3画图和以图生图功能)、联网功能、chatpdf功能、语音输入和图片OCR识别等。此外,ChatAA还支持创建专属智能体的功能,允许用户上传https://www.bgrdh.com/sites/24456.html
8.java实现个人微信号聊天laojean的技术博客ClientChat. 本篇文章围绕聊天室的聊天界面ClientChat,叙述其中各种功能的实现。开始我们还是给出ClientChat最终GUI效果的两个展示,通过展示来直观认识各种功能。 关于控件. JSplitPane分割窗格的使用. 上面展示的GUI中实际上有三个分割窗格,比较明显的是中间这一道,将整个UI分为左右两边的分割窗格。我们首先给出代码段,https://blog.51cto.com/u_14256/12153256
9.想学英语聊天?先搞懂“Chat”怎么读!老外总爱说“Chat with me”,你是否也想知道“Chat”怎么读呢?别着急,今天就来教你! 很多小伙伴看到“Chat”就傻眼了,这单词看起来有点眼生,怎么读呢?其实很简单,它读起来就和中文的“聊天”很像,发音类似于“切特”。 记住,两个“T”都读成“特”音,不要读成“特”和“特”哦! 想要更准确地https://localsite.baidu.com/article-detail.html?articleId=29441974&ucid=PjbkP1RzP1b&categoryLv1=%E6%95%99%E8%82%B2%E5%9F%B9%E8%AE%AD&ch=54&srcid=10004
10.ChatGPT国内中文使用Ai聊天SD分享导航站SD分享导航站ChatGPT 国内中文使用Ai聊天 ChatGPT 国内中文可用网址,每天5次免费使用GPT3.5版本。 现在开始收费 了,但有一点点免费额度。。 网址:https://chat.7jm.cnhttps://home.designshidai.com/6019.html
11.AppStore上的“Chatrandom”提供1000亿连接后,Chatrandom已经彻底改变了人们在网上遇见陌生人的方式。 Chatrandom于2011年推出,每月使用人数达数百万人,是一款功能强大的工具,能够即时结识新朋友并进行视频聊天,调情,约会,或仅仅是为了结识您从未见过的人。 Chatrandom易于使用且有趣,可与其他用户进行视频聊天配对,向右滑动即可与新用户联系。就是https://itunes.apple.com/cn/app/id1452118078
12.awesomechatgpt/README.mdatmain·lyhiving/awesomechatanywhere/GPT_API_free - Free ChatGPT API Key,免费ChatGPT API,支持GPT4 API(免费),ChatGPT国内可用免费转发API,直连无需代理。可以搭配ChatBox等软件/插件使用,极大降低接口使用成本。国内即可无限制畅快聊天。 vpncn/vpncn.github.io - 2024中国翻墙软件VPN推荐以及科学上网避坑,稳定好用。对比SSR机场、https://github.com/lyhiving/awesome-chatgpt/blob/main/README.md
13.人工智能浏览器Opera中的人工智能聊天和创作Opera在Opera 的桌面和移动设备上与人工智能聊天。ChatGPT 和 Aria(Opera 的免费、无限制浏览器人工智能)无缝集成到您的浏览器中。https://www.opera.com/zh-cn/features/browser-ai
14.Chat聊天分析vibe26Chat聊天分析 分类: Android平台 2015-03-25 15:33:00 以一个安卓程序为例 MainActivity.java package cn.com.xiebiao.mytest; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.view.View; import android.widget.Button; import android.widget.http://blog.chinaunix.net/uid-29532371-id-4916141.html
15.手把手教你如何和ChatGPT聊天一个数据人的自留地小诺已经迫不及待的想立刻体验ChatGPT了。 老汤姆: “这个也没有那么难,主要分四步。第一步,搭梯子;第二步,注册ChatGPT账号;第三步,有短信接码平台完成手机号验证;第四步,登录账号,和ChatGPT聊天。你看,是不是很简单?“ 数据产品经理小诺眉头紧锁: https://www.shangyexinzhi.com/article/6390972.html
16.chatgpt聊天栏输入不了中文导读:为帮助您更深入了解chatgpt聊天栏输入不了中文,小编撰写了chatgpt聊天栏输入不了中文,chatgpt中文版下载不了,chatgpt不能翻译中文了,chatgpt聊天记录不见了,chatgpt怎么用中文聊天等5个相关主题的内容,以期从不同的视角,不同的观点深入阐释chatgpt聊天栏输入不了中文,希望能对您提供帮助。 http://chatgpt.cmpy.cn/article/2400992.html
17.ChatGPT聊天体验我们讨论了与ChatGPT相关的一系列话题,并且尝试了通过API去调用它,来开发自己的NLP应用。 最近十年,聊天软件等即时通讯软件与智能手机一起改变了人们的沟通方式,对人们的生活和工作,社会的政治、经济、科技与文化等都带来了巨大的影响,它们挖掘的是人际关系网络。不久的将来,对话界面的学习与研究,知识的获取https://www.jianshu.com/p/51fa9082494f