(课设)C/S架构即时聊天软件开发(QT)
(课设)C/S架构即时聊天软件开发
一、引言
项目概述
项目目的:在已掌握的数据结构和算法的相关知识基础上,借助数据库和 Qt 以团队形式开发个性化即时通讯软件。
项目背景:
- 通过前两年学校课程的学习,我们初步掌握了计算机领域的基础知识及常用算法,并对计算机结构系统的设计有了初步认识,在此基础上,需要通过适当程度的项目开发工作,将学校中学到的知识应用于实践,在实践中发现自己的知识薄弱之处,不断反思提升,并锻炼团队工作能力,为未来的职业生涯打下基础
- 随着时代的发展,人与人之间的距离逐渐被拉近,人们对于通讯的即时性的要求也越来越高,即时通讯软件也成为业界开发重点,相关领域的积累也较为丰富
- 在老师的指导下,我们初步掌握了 Windows 环境下 QT 的安装和开发技能,并持续学习 MySQL 和服务器相关知识,为项目的开发打下了较为完善的基础。
项目意义:
- 通过项目开发,在实战中检验自己的课程学习能力和掌握程度,在实战的思考与反思中提升自己的技术水平
- 团队项目开发过程中相互学习,相互帮助,锻炼自己的团队合作意识和分工协作能力,积累工作经验
- 在开发过程中收集相关领域的学习资料,从而接触到业界最前沿的研究工作,拓展自己的视野
需求分析
人与人之间良好而高效的沟通,是现代社会运行的基础条件。而在社会发展的浪潮之下,社会分工开始变得更加复杂,更加多样化,每个人对于社会交流和信息分享的需求也更加个性化。在这种情况下,针对特定人群的即时通讯软件就体现出其在保护个人隐私,方便信息分享方面的独特优势,,其价值也体现于此。
运行环境
客户端 windows10、服务器 Linux 端、Qt Creator
二、项目设计
设计思路
将即时通讯软件命名为 OChat,以客户端/服务器(C/S)的模式来设计。客户端负责对话功能,接受用户的输入数据并发送,显示接受的数据;服务器将具体的业务逻辑编入程序中,维护数据库,承担用户的信息储存和消息中转作用。
模块功能介绍
序号 | 模块 | 功能点 | 功能点详细内容 |
---|
模块结构图
模块名称 | 模块类型 | 概要说明 |
---|
程序流程图
登录时序
注册时序
通信时序图
功能设计分工
设计登录注册页面 Ui | 刘睿 |
---|
三、详细设计
服务器部分:
服务器设计:服务器端由 socket 通讯部分、IO 复用部分(多并发)、数据库操作部分(MySQL API for C)、客户端消息处理部分以及功能实现函数组成。
其逻辑功能结构如下:
socket 通讯部分、IO 复用部分、客户端消息处理部分置于主函数 int main()中,相互穿插。在 socket 通讯部分的 listen()函数之后,通过 fd_set 和 select()函数、clifd[i]数组进行多并发,每有一个客户端通过连接发来消息,就进入客户端消息处理部分,对客户端消息进行解析,进而根据结果调用各个功能函数,在调用功能函数的过程中,会与数据库进行交互,同时将相应的反馈信息通过 send()函数发送给客户端。
所涉技术:
- 使用 socket 进行网络通讯
- 使用 IO 复用的 select 实现多并发
- 使用 sscanf()函数进行字符串的分解存入
- 使用 MySQL API for C 建立与数据库的连接并使用数据库
核心功能:
- 与客户端进行通讯
- 同时与多个客户端进行通讯
- 正确处理客户端的消息
- 与数据库建立连接并使用数据库
- 处理用户的不同请求(登录注册、增删好友、发送消息、修改密码、获取好友列表等)
- 判断用户是否在线以及是否已经离线
数据库部分:
user_tb 用户表
user_name varchar(48), user_password varchar(16)
存储用户的用户名和密码。
userfd_tb 已登录用户表
user_name varchar(48), user_confd int
存储在线用户的用户名和对应句柄。
friend_tb 好友关系表
usera_name varchar(48), userb_name varchar(48)
存储用户的用户名和该用户好友的用户名。
message_tb 未读消息表
target_name varchar(48), message varchar(1024), sender_name varchar(48)
存储消息内容、发送者和接收者。
firreq_tb 未读好友申请表
sender varchar(48)(申请发送者), revc varchar(48)(申请接收者)
存储好友申请的发送者和接收者。
accreq_tb 未读好友申请回复表
req_target varchar(48)(申请目标/申请接收者), req_sender varchar(48)(申请发送者), attitude char(1)(接收者态度)
存储申请的发送者和接收者和同意/拒绝好友申请的结果。
客户端部分:
- 主体功能界面为登录界面和聊天界面
- 主要功能界面采用隐藏系统窗口框的方式,自己编写窗口的关闭和最小化界面
- 在登录界面设置登录注册按钮和修改密码通道
- 登录打开界面时给出好友列表,用户双击好友开始聊天
- 当双击好友聊天,好友列表自动向右收缩,在左方显示聊天输入框和好友头像
- 聊天框支持回车输入和 ESC 键关闭当前聊天框
- 在好友列表单击好友可以在右侧查看好友信息
- 好友列表下方设置添加 | 删除好友和关闭会话功能按钮
- 对所有可见按钮和输入框应用样式表进行美化
四、实现方案
服务器部分:
服务器功能实现方案:
- 与客户端进行通讯:使用 UNIX BSD 的套接字(socket)。服务器端先初始化 socket(socket()函数),然后与端口绑定(bind()函数),对端口进行监听(listen()函数),调用 accept()函数阻塞,等待客户端连接。在这时如果有个客户端初始化一个 socket,然后连接服务器,如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。
- 多并发:使用 select IO 复用机制。在 listen()函数后,定义两个 fd_set,分别为 allset 和 rset,使用 FD_SET 函数首先将服务器套接字放入集合中,然后在一个大循环中反复调用 select 函数,让我们的程序监视多个文件句柄的状态变化,每有一个句柄连接上就从其那里接收消息。
- 处理客户端消息:与客户端首先制定好通信协议,使用 sscanf 函数将客户端发送过来的消息进行分解处理,读出报头来确定客户端是请求什么操作,进而调用对应函数。
- 使用 MySQL API for C 中提供的 mysql_init 和 mysql_real_connect 函数来初始化数据库并建立连接。使用 sprintf 函数格式化好所需的 SQL 语句,利用 mysql_query 函数来进行查询,调用 mysql_store_result 和 mysql_fetch_row 来获取和逐行读取结果集。
- 利用设计好的通讯协议,使用 sscanf 函数将客户端发送过来的消息进行分解处理,读出报头来确定客户端是请求什么操作,进而调用对应函数。然后在对应函数中处理。
注册:读取客户端发送的注册信息(包括用户名、密码、性别、所在地、生日等),然后将用户名与数据库中存有的名字进行对比,如有重复,则返回客户端错误信息:ERR| 用户名已存在。如无重复用户名,则将所有信息存入数据库中。
登录:读取客户端发送的登录信息,首先检查该用户名是否存在,如不存在向客户端返回错误信息,如存在则 将该用户名在数据库中保存的密码取出,与发送的密码进行对比,相同则完成登录,将该用户名与该用户名对 应的句柄存入数据库;不同则返回错误信息。
添加好友:处理客户端发送的信息,首先检查要添加的用户名是否存在,如不存在向客户端返回错误信息,如 存在则将该用户名与发送信息的用户名绑定存入数据库中的好友关系表中。
数据库部分:
user_tb 用户表
在用户使用登陆功能时核对用户输入的用户名和密码,如果用户名与密码对应正确则返回登录成功,否则返回登录失败。
userfd_tb 已登录用户表
用于存储在线用户的用户名,标记每一位用户的在线/离线状态。客户端收到要发送给用户的消息时首先判断用户是否在线,用户在线则直接发送到其客户端,用户离线则暂时存储。在离线用户上线后将消息发送给此用户。
friend_tb 好友关系表
记录用户之间的好友关系,用户的好友列表中会出现所有与其存在好友关系的其他用户,点击好友列表中的好友才能够进行聊天,实现有好友关系的用户之间才可以互相聊天这一功能限制。
message_tb 未读消息表
存储将要发送给离线用户的消息。在记录的离线接收者上线后将存储的消息发送给该用户,并显示所记录的消息发送者。实现发送离线消息的功能。
firreq_tb 未读好友申请表
存储将要发送给离线用户的好友申请,在记录的离线好友申请接收者上线后向其发送好友申请,并显示好友申请的发送者。实现向离线用户发送好友申请的功能。
accreq_tb 未读好友申请回复表
存储将要发送给离线用户的好友申请回复,在记录的好友申请发送者上线后向其发送好友申请回复,告知对方同意/拒绝了好友申请,并显示对方的用户名。在对方同意好友申请的情况下,好友列表会发生改变。实现向离线用户发送好友申请回复的功能。
客户端部分:
系统窗口框不可见:
设置不可见后使窗口可拖动:通过设置捕捉鼠标事件和窗口相对位置来实现
改变控件样式表(以按钮为例):
页面之间的数据传输(以初始界面和聊天界面为例):
自定义 QtableWidget 标签:
标签的关闭(结束聊天):
捕捉键盘事件:
数据结构:
富文本设置文本格式:
登录界面: 注册界面:
修改密码: 添加/删除好友:
好友列表: 聊天界面:
五、系统测试
测试分类 | 测试内容 | 测试方法 | 判定基准 | 执行結果 |
---|