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群组聊天- 支持创建多个群组,方便团队协作。 文件分享- 用户可以便捷地上传并分享各种类型的文件。 自定义部署- 开源特性允许你根据需求在自己的服务器上部署,保护数据隐私。 API 扩展- 提供API接口,便于与其他系统集成或扩展功能。 使用场景 小团队沟通- Chat 可以作为一个简单易用的内部沟通工具,替代邮件等传统沟通https://blog.csdn.net/gitblog_00030/article/details/137134682
2.chat什么意思chat什么意思 聊天的ChatTogether 您好,很高兴与您聊天!关于“chat”这个词,它的意思是“聊天”或“交谈”。它通常用于描述两个人或多人之间的交流对话。在数字化时代,我们还经常看到“chat”用在各种在线聊天工具或平台上,比如社交媒体、即时通讯软件等。希望这个解释能帮到您!您还有其他问题吗?https://agents.baidu.com/content/question/42f472e55c73cc883a8c64cf
3.chatchat 美[tt]英 [tt] v.聊天;交谈;闲谈;闲聊 n.聊天;闲谈;闲聊;网上聊天 网络聊天室;胆碱乙酰转移酶(choline acetyl transferase);谈天 复数:chats 过去式:chatted 现在分词:chatting chat 搭配 adj.+n. quiet chat 权威英汉双解英-汉英-英网络释义https://www.qifanda.com/dict/Chat.html
4.聊天的翻译是: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
5.LiveChat实时聊天软件和服务台软件LiveChat – 高级商业版实时聊天软件和服务台软件。来自 150 个国家的超过 25,000 家公司使用 LiveChat。免费试用!https://www.livechat.com/cn
6.HuggingChat官网,个性化聊天机器人,ChatGPT平替方案,开源HuggingChat是最大开源社区hugging face旗下ai聊天机器人项目,有300亿参数! 是ChatGPT的一个开源竞争者,展示了Hugging Face团队对开源AI的执着。HuggingChat是一个强大的聊天机器人,采用了Open Assistant最新的模型,一个顶尖的开源聊天模型,以及Hugging Face Inference API,实现在生产环境中无缝地部署和管理NLP模型。 https://feizhuke.com/sites/huggingchat.html
7.GitHubLeoLionni/flutter聊天列表页面 登录成功,进入到聊天列表页面。 1.请求聊天列表接口/chat_list,获取聊天列表并展示。(后台定义接口类ChatListController,注意客户端接口请求是要带上token的,因为服务端会做token验证。若token无效,则返回401错误码)。 getChatList() async { Dio dio = Dio(BaseOptions( baseUrl: GetIt.instance<AppChttps://github.com/ariagecheney/flutter_chat
8.HuggingChat官网,个性化聊天机器人,ChatGPT平替方案,开源,免费HuggingChat是最大开源社区hugging face旗下ai聊天机器人项目,有300亿参数! 是ChatGPT的一个开源竞争者,展示了Hugging Face团队对开源AI的执着。HuggingChat是一个强大的聊天机器人,采用了Open Assistant最新的模型,一个顶尖的开源聊天模型,以及Hugging Face Inference API,实现在生产环境中无缝地部署和管理NLP模型。 https://biemoyu.com/sites/huggingchat.html
9.手把手教你如何和ChatGPT聊天一个数据人的自留地小诺已经迫不及待的想立刻体验ChatGPT了。 老汤姆: “这个也没有那么难,主要分四步。第一步,搭梯子;第二步,注册ChatGPT账号;第三步,有短信接码平台完成手机号验证;第四步,登录账号,和ChatGPT聊天。你看,是不是很简单?“ 数据产品经理小诺眉头紧锁: https://www.shangyexinzhi.com/article/6390972.html
10.ChatGPT包含前后台,支持打字效果输出流式输出,支持AI聊天次数限制,支持分享增加次数等功能。开源版禁止商用,仅供学习交流,禁止倒卖。感谢Star! 技术栈:JDK8 + SpringBoot + Vue2 + Uniapp + Mysql Github地址:https://github.com/oldinaction/ChatGPT-MP Gitee地址(国内访问更快):https://gitee.com/smalle/ChatGPT-MPhttps://gitee.com/TakingCat/ChatGPT-MP
11.可查看其他用户聊天记录,ChatGPT爆出大BUGChatGPT 遇到了大麻烦——被爆用户聊天记录泄露。https://www.freebuf.com/news/361514.html
12.易聊天在不同的设备上登录易聊天,能获得编辑过的所有话术,支持实时话术 同步,让话术如影随行。 易聊天图文教程 易聊天视频教程 支持吸附多种聊天工具 解决工作中要使用多种聊天工具,但快捷回复不互通的问题。实现兼容不同聊天工具共用同一套话术模板 微信 企业微信 https://www.yiliaotian.com/
13.2024土耳其最受欢迎的社交软件/App排行及推荐(华人交友,聊天,约会使用Snapcode添加好友,首先通过拍摄您的朋友 Snapcode 来获取它的图片。选择幽灵图标, 然后去添加朋友。在这里将看到多个选项, 选择 “Snapcode”。上传你的朋友的 Snapcode 照片, 你已经采取了, 你的朋友将被添加到你的 Snapchat。 聊天:通过实时消息与朋友保持联系,或通过群组故事分享您的一天。一次与多达 16 https://www.extrabux.cn/chs/guide/7142551
14.Shopify即时聊天工具Tidiolivechat减少用户抛弃购物车的概率正如前面介绍的那样,除了最核心的聊天功能外,Tidio Live Chat还有很多强大的功能,在这里我只挑选一些常用的功能进行设置演示,没有提及到的功能大家可以自己进行摸索。 1.Tidio支持桌面版以及手机端App下载 具体操作步骤:依次进入Tidio后台-Setting-Desktop&Mobile,找到对应版本下载即可,当然你也可以通过Google Play查找Tidiohttps://www.cifnews.com/article/49176/
15.CHATGPT如何使用简单教程5.使用其他功能:CHATGPT还提供了其他一些功能,如语音识别、问答等。你可以在聊天室中输入“help”查看http://chatgpt.kuyin.cn/ask/54190.html
16.中文ChatGPT软件哪个好用电脑教程HerAI是基于ChatGPT构建的聊天写作机器人,支持编写代码、写文案、翻译等,提供ChatGPT3.5、4.0两个聊天机器人,价格有所差异。3.5版本支持新用户5次免费提问。 三、iChatX iChatX提供对话及创作两种ChatGPT沟通模式,其中创作模式支持用户快速地写作文章、学术论文、商业报告、公文等。首次安装支持20次免费提问,无广告,相https://www.koudaipe.com/funny/7423.html
17.网红聊天机器人ChatGPT的碳排放究竟多高?界面新闻先是微软宣布再砸100亿美金入股OpenAI,然后亚马逊和美版“今日头条”BuzzFeed宣布将在日常工作中启用ChatGPT,同时,百度也宣布将于3月推出“中国版”的ChatGPT聊天机器人。在多家科技公司推波助澜后,ChatGPT瞬间引发全球关注。 一些网友开始疯狂测试ChatGPT,比如写代码、写剧本、写小说、写新闻、写作业、广告文案、知识https://www.jiemian.com/article/8914963.html
18.ChatRobotChatRobot-聊天机器人ai绘画 17+ 人工智能AI问答、AI绘图神器 Suzhou Chengfeng Network Technology Co., Ltd. Designed for iPad Free Offers In-App Purchases Screenshots iPad iPhone Description 一款智能AI问答、AI绘画的APP,利用大模型生成式AI技术回答用户许多问题。无论您是在学习、工作还是生活中遇到了问题,https://apps.apple.com/ie/app/chatrobot-%E8%81%8A%E5%A4%A9%E6%9C%BA%E5%99%A8%E4%BA%BAai%E7%BB%98%E7%94%BB/id1671107971
19.免费chatGPT网页版3.5,免费chatGPT网页版知乎最近,你是否感觉到在和聊天人工智能助手进行交谈时,它所给出的回应变得更加智能和贴近生活了?没错,这就是因为ChatGPT网页版更新了!新版本的ChatGPT网页版3.5在保留原有的简单易用性的基础上,为用户带来了更加智能、更加灵活、更加贴近生活的聊天体验。 http://ai.aigou2019.com/archives/4225
20.ChatGPT新增临时聊天功能,对话不留痕IT之家5 月 1 日消息,OpenAI 近日连续发布更新,为 ChatGPT 免费和 Plus 用户带来更多数据控制功能。此次更新赋予用户更多对话历史记录的管理权限,并新增了“临时聊天”功能。 此前,选择不贡献对话数据以训练模型的用户无法访问自己的聊天历史记录。最新更新取消了这一限制,无论用户是否选择贡献数据,现在都可以访问聊天https://www.ithome.com/0/765/502.htm
21.聊天室Chatroom17岁的青年威廉(阿隆·强森 Aaron Johnson 饰)在网上建立了一个聊天室,此后不久,伊娃(伊莫珍·波茨 Imogen Poots 饰)、吉姆(马休·比尔德 Matthew Beard 饰)、艾米莉(汉娜·莫瑞 Hannah Murray 饰)、莫(丹尼尔·卡鲁亚 Daniel Kaluuya 饰)这几个分处不同地方、彼此陌生的年轻人相继聚集于此。他们畅谈心事,尽情https://movie.douban.com/subject/3279065