# syb-chat **Repository Path**: syb4750/syb-chat ## Basic Information - **Project Name**: syb-chat - **Description**: 分布式即时通讯项目 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-08-18 - **Last Updated**: 2025-08-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 分布式即时通讯项目 ![总体框图](Framework.png) 这是一个全栈的分布式即时通讯项目,前端基于QT实现气泡聊天对话框,通过QListWidget实现好友列表,利用GridLayout和QPainter封装气泡聊天框组件,基于QT network模块封装http和tcp服务。支持添加好友,好友通信,聊天记录展示等功能,仿微信布局并使用qss优化界面。 后端采用分布式设计,分为GateServer网关服务,多个ChatServer聊天服务,StatusServer状态服务以及VerifyServer验证服务。 各服务通过grpc通信,支持断线重连。GateServer网关对外采用http服务,负责处理用户登录和注册功能。登录时GateServer从StatusServer查询聊天服务达到负载均衡,ChatServer聊天服务采用asio实现tcp可靠长链接异步通信和转发, 采用多线程模式封装iocontext池提升并发性能。数据存储采用mysql服务,并基于mysqlconnector库封装连接池,同时封装redis连接池处理缓存数据,以及grpc连接池保证多服务并发访问。 通过tlv方式(消息头(消息id+消息长度)+消息内容)封装消息包防止粘包。通过心跳机制检测连接可用性。 ## Client 客户端,采用Qt5实现,使用qss美化界面,封装单例基类,通过配置文件管理GateServer信息。 实现了定时按钮,点击后显示倒计时,倒计时结束后再次可点击;实现了六态Label;实现气泡聊天对话框等。 HttpMgr类管理http发送接收请求,使用QJsonDocument解析Json,使用QNetworkRequest发送http请求并处理响应。 TCPMgr类管理TCP连接,使用QTcpSocket实现,维持一个长连接,实现服务器和客户端双向通信 因为客户端发送数据可能在任何线程,为了保证线程安全,在要发送数据时发送TcpMgr的SigSendData信号,然后实现接受这个信号的槽函数。 UserMgr类,统一管理用户数据。 ### 登录界面 #### 主动操作 + 点击注册按钮:跳转到注册界面。 + 点击忘记密码:跳转重置密码界面。 + 点击登录:发送http post请求到GateServer。 #### http回包处理 + 用户登录回包处理:登录成功接收uid, host, port, token, 发送信号通知tcpMgr发起长链接。 ### 注册界面 #### 主动操作 + 点击获取按钮:发送http post请求,将用户邮箱发送到GateServer,获取验证码。 + 点击确认按钮:发送http post请求,将用户信息发送到GateServer,完成用户注册。 + 点击取消按钮:返回登录界面。 #### http回包处理 + 获取验证码回包:如果成功,提示"验证码已发送到邮箱,注意查收"。 + 用户注册回包:如果成功,提示“用户注册成功”,接收用户email和uid,切换回登录界面。 ### 重置密码界面 #### 主动操作 + 点击获取按钮:发送http post请求,将用户邮箱发送到GateServer,获取验证码。 + 点击确认按钮:发送http post请求,将用户信息发送到GateServer,完成密码重置。 + 点击取消按钮:返回登录界面 #### http回包处理 + 获取验证码回包:如果成功,提示"验证码已发送到邮箱,注意查收"。 + 重置密码回包:如果成功,提示"重置成功,点击返回登录"。 ### 聊天界面 左侧切换聊天界面和联系人界面,上方搜索框可以查找好友,搜索到数据库中存在的信息后可以申请添加好友。右侧在聊天界面下可以发送信息;在联系人界面下可以查看联系人信息,点击消息图标跳转到聊天界面。 #### 主动操作 + 查找好友:点击查找Item后,发送TCP消息ID_SEARCH_USER_REQ到ChatServer,弹出等待对话框,等待网络回包。 + 添加好友:点击确定添加好友后,发送TCP消息ID_ADD_FRIEND_REQ到ChatServer。 + 验证添加好友:当有人添加我为好友时,新的朋友界面点击添加后,弹出确认申请对话框,继续点击确认按钮后,发送TCP消息ID_AUTH_FRIEND_REQ到ChatServer。 + 发送消息:聊天界面点击发送按钮后,发送TCP消息ID_TEXT_CHAT_MSG_REQ到ChatServer,聊天框气泡显示发送内容,将聊天记录添加到内存中。 #### tcp回包处理 + 登录处理:添加好友申请列表,添加好友列表,跳转到聊天界面。 + 查找好友处理:如果查找的是自己,nothing。如果查找的已经是自己的好友,跳转到与该好友的聊天界面。如果查找的不是自己的好友,弹出添加对话框。如果查找的不是已经注册的用户,弹出查找失败对话框。 + 收到添加好友请求处理:左侧联系人图标显示红点,联系人界面新的朋友Item显示红点,右侧显示添加好友信息。 + 认证好友回复处理:添加好友信息界面该好友显示为已添加,聊天界面添加该好友为第一个,联系人界面添加好友信息。 + 自己添加好友,对方同意后处理:聊天界面添加该好友为第一个,联系人界面添加好友信息。 + 发送消息回复处理:确认已发送。 + 收到别人发送的消息处理:更新聊天界面、联系人信息。将聊天记录添加到内存中。 ## GateServer 网关服务器,接收http请求并应答,处理注册,获取验证码,用户登录。 使用了boost库的Beast‌处理网络,使用jsoncpp解析json,使用redis-plus-plus连接Redis服务器,使用Mysql Connector C++ 这个库来访问mysql。 Cserver类定义acceptor,用于事件循环的上下文iocontext,Start函数每次从IOContext Pool中获取一个连接。 HttpConnection类实现http接收、处理、回复,使用http::async_read函数读取收到的数据,使用定时器实现发送超时检测。 主函数中初始化上下文iocontext以及启动信号监听ctr-c退出事件, 并且启动iocontext服务。 通过配置文件管理相关信息,ConfigMgr类用来读取和管理配置,SectionInfo类管理key和value。 封装ASIO IOContext Pool,让多个iocontext跑在不同的线程中。 VerifyGrpcClient中封装RPConPool,当我们想连接grpc server端时,可以通过池子获取连接,用完之后再返回连接给池子。 封装RedisMgr类用于redis操作,它是个单例类并且可接受回调,封装了redis连接池。 封装了mysql连接池,MysqlMgr类用于mysql操作。 StatusGrpcClient中封装了StatusConPool。 ### http请求处理 + 获取验证码处理:收到获取验证码的post请求后,通过gRPC请求VerifyServer发送验证码。返回请求的邮箱。 + 用户注册处理:先查找redis中email对应的验证码是否正确,不正确返回错误。正确在数据库中注册用户。返回用户信息。 + 用户重置密码处理:先查找redis中email对应的验证码是否合理,查询数据库判断用户名和邮箱是否匹配,然后更新mysql数据库中的密码。返回用户信息。 + 用户登录处理:先查询数据库判断邮箱和密码是否匹配。再调用grpc请求给StatusServer,获取合适的服务器信息并返回。 ## VerifyServer 验证服务器,使用nodejs实现,安装grpc-js用于实现grpc,安装proto-loader用来动态解析proto文件,安装nodemailer用来发送邮件,安装ioredis用来访问redis。 获取验证码之前可以先查询redis,如果没查到就生成uid并且写入redis并设置过期时间。 使用uuidv4()函数生成随机验证码,将随机生成的验证码发送到注册用户邮箱并返回给GateServer。 ## StatusServer 状态服务器,管理ChatServer的状态信息,通过配置文件管理相关信息。 监听grpc服务。 通过boost::uuids::random_generator()函数产生随机token,并存入Redis 查找连接数较少的ChatServer,实现负载均衡。 ## Redis 存储验证码,key为邮箱,value为验证码,过期时间为3min。 存储服务器token,key为utoken前缀+用户id,value为token。 存储服务器连接数目。 储存用户信息。 ## Mysql user表存储用户信息。 friend_apply表存储好友申请信息。 friend表存储好友信息。 ## ChatServer 基于asio实现tcp服务器。 连接成功后先读取包头,再读取包体,调用asyncReadFull读取整个长度,然后解析收到的数据,前两个字节为id,之后两个字节为长度,最后n个长度字节为消息内容。 读取包体完成后,在回调中继续读包头。以此循环往复直到读完所有数据。如果对方不发送数据,则回调函数就不会触发。不影响程序执行其他工作,因为采用的是asio异步的读写操作。 解析完包体后会调用LogicSystem单例将解析好的消息封装为逻辑节点传递给逻辑层进行处理。 实现grpc客户端和服务端。这样能实现两个chatserver之间端对端的通信。 每当服务器chatserver启动后,都要重新设置一下用户连接数管理。 分两个线程监听tcp服务和grpc服务。 启动一个定时器,每隔60s检测一下所有连接,判断连接是否“活着”。 ### tcp请求处理 + 用户登录处理:先从redis获取用户token是否正确。然后从redis中查找用户信息,如果没有找到再去mysql中查找,并写入redis。接这从数据库获取好友申请列表和好友列表,将服务器的连接数量增加并写入redis。绑定用户id和服务器ip并写入redis。 + 查找好友处理:通过用户id或者name优先从redis中查找用户信息,如果没有找到再去mysql中查找,并写入redis。 + 添加好友处理:先将好友申请更新到mysql中,查询redis查找touid对应的server ip。如果两个客户端连接同一个服务器,直接通知另一个客户端有申请消息。如果不在同一个服务器,调用grpc通知另一个服务器。 + 验证好友处理:先将好友申请更新到mysql中,并更新mysql中的好友列表。查询redis查找touid对应的server ip。如果两个客户端连接同一个服务器,直接通知另一个客户端有认证通过消息。如果不在同一个服务器,调用grpc通知另一个服务器。 + 发送消息处理:查询redis查找touid对应的server ip,如果两个客户端连接同一个服务器,直接通知另一个客户端有聊天消息。如果不在同一个服务器,调用grpc通知另一个服务器。 ### gRPC请求处理 + 添加好友请求处理:先查找用户是否在本服务器,不在直接返回。在的话,发送tcp消息通知对方。 + 认证好友请求处理:先查找用户是否在本服务器,不在直接返回。在的话,发送cp消息通知对方。 + 发送消息请求处理:先查找用户是否在本服务器,不在直接返回。在的话,发送cp消息通知对方。