前情回顾
前面我们搞定了1,2,3以及5过程

今天主要完成
4,6和7
资源服务器grpc设置
因为资源服务器要通知ChatServer,所以要设置grpc客户端
完善下proto协议,新增消息通知请求

具体代码逻辑
1 | message NotifyChatImgReq{ |
实现grpc客户端逻辑如下:
1 |
|
具体实现
1 |
|
实现了通知接口,用来通知ChatServer图片消息上传完成,让ChatServer再通知其他客户端.
ChatServer响应资源服务器通知
ChatServer的proto也需要进行同样配置,这里略去
具体在ChatServiceImpl中添加响应消息通知的逻辑
1 | Status ChatServiceImpl::NotifyChatImgMsg(::grpc::ServerContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response) |
通过Session通知客户端
1 | void CSession::NotifyChatImgRecv(const ::message::NotifyChatImgReq* request) { |
客户端获取通知
客户端收到服务器通知后,会优先查看本地资源是否存在,如果存在则直接加载图片,添加聊天记录到页面。
如果不存在则组织下载,但是也需要将消息添加到聊天界面。
1 | _handlers.insert(ID_NOTIFY_IMG_CHAT_MSG_REQ, [this](ReqId id, int len, QByteArray data) { |
收到服务器通知后,开始构造json数据,发送ID_IMG_CHAT_DOWN_REQ请求
聊天记录添加
客户端在请求服务器资源的时候,因为本地没有资源,可以先在聊天界面生成一个预览的空白图片,同时显示进度条
这部分逻辑是在客户端的tcpmgr中处理服务器通知聊天消息的逻辑里
1 | _handlers.insert(ID_NOTIFY_IMG_CHAT_MSG_REQ, [this](ReqId id, int len, QByteArray data) { |
客户端将图片消息发送给界面显示
在ChatDialog的构造函数中添加信号槽链接
1 | connect(TcpMgr::GetInstance().get(), &TcpMgr::sig_img_chat_msg, |
ChatDialog收到该信号后,会触发添加消息的逻辑
1 | void ChatDialog::slot_img_chat_msg(std::shared_ptr<ImgChatData> imgchat) { |
添加其他消息的逻辑, 此处都是将其他人发送的图片消息添加到聊天界面显示
1 | void ChatPage::AppendOtherMsg(std::shared_ptr<ChatDataBase> msg) { |
资源服务器响应下载请求
LogicWorker中增加请求的处理
1 | _fun_callbacks[ID_IMG_CHAT_DOWN_REQ] = [this](std::shared_ptr<CSession> session, const short& msg_req_id, |
LogicWorker将请求投递给FileSystem队列,FileSystem队列排队处理消息,被DownloaderWorker处理
1 | void DownloadWorker::task_callback(std::shared_ptr<DownloadTask> task) |
资源服务器每次收到请求后,由DownloadWorker从队列中获取请求,查询服务器资源,将资源按照seq计算偏移量最后读取数据发送给客户端。
客户端存储下载的资源
客户端需要存储服务器传输的资源
1 | _handlers.insert(ID_IMG_CHAT_DOWN_RSP, [this](ReqId id, int len, QByteArray data) { |
通过QFile类实现文件写入。
客户端进度显示
为了让客户端更为直观的显示下载进度,可以在收到服务器消息后,将文件下载进度同步给界面,同时显示支持暂停和继续
进度通知在上述逻辑中
1 |
|
同样是在ChatDialog构造函数中添加消息链接
1 | //接收tcp返回的下载进度信息 |
进度处理槽函数
1 | void ChatDialog::slot_update_download_progress(std::shared_ptr<MsgInfo> msg_info) { |
在ChatPage中详细处理更新
1 | void ChatPage::UpdateFileProgress(std::shared_ptr<MsgInfo> msg_info) { |
PicBubble中完成状态显示
1 | void PictureBubble::setProgress(int value, int total_value) |
断点续传
因为在客户端收到服务器通知的图片聊天信息的时候,已经通过sig_img_chat_msg将消息发送给ChatDialog添加到页面上了。同时传输了图片的状态为下载中。
点击继续和暂停的逻辑可以复用PicBubble的逻辑
1 | void PictureBubble::onPictureClicked() |
接下来我们响应暂停和继续,这部分逻辑也已经复用之前的逻辑即可
暂停逻辑
1 | void ChatPage::on_clicked_paused(QString unique_name, TransferType transfer_type) |
恢复逻辑
1 |
|
发送继续下载信号通知FileTcpMgr继续下载
1 | void FileTcpMgr::ContinueDownloadFile(QString unique_name) { |
FileTcpMgr响应下载逻辑
1 | void FileTcpMgr::slot_continue_download_file(QString unique_name) { |
通过上述逻辑可以实现客户端的断点下载和暂停。
效果演示

源码链接
https://gitee.com/secondtonone1/llfcchat
注意第二季分支为Season_2