Files
MyChat_Client/network/netclient.cpp
2025-06-17 18:40:02 +08:00

286 lines
9.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "netclient.h"
#include "../model/datacenter.h"
using namespace model;
namespace network {
NetClient::NetClient(model::DataCenter* dataCenter)
:dataCenter(dataCenter)
{
initWebSocket();
}
void NetClient::ping()
{
QNetworkRequest httpReq;
httpReq.setUrl(QUrl(HTTP_URL + "/ping"));
QNetworkReply* httpResp = httpClient.get(httpReq);
connect(httpResp, &QNetworkReply::finished, this, [=]() {
//到这里面,说明响应已经回了
if (httpResp->error() != QNetworkReply::NoError) {
//请求失败
LOG() << "HTTP请求失败" << httpResp->errorString();
httpResp->deleteLater();
return;
}
//获取到响应的body
QByteArray body = httpResp->readAll();
LOG() << "响应的内容: " << body;
httpResp->deleteLater();
});
}
void NetClient::initWebSocket()
{
//准备好所需要的信号槽
connect(&websocketClient, &QWebSocket::connected, this, [=]() {
LOG() << "webSocket 连接成功";
//连接成功之后,进行发送身份认证
sendAuth();
});
connect(&websocketClient, &QWebSocket::disconnected, this, [=]() {
LOG() << "webSocket 连接断开";
});
connect(&websocketClient, &QWebSocket::textMessageReceived, this, [=](const QString& message) {
LOG() << "webSocket 收到文本消息 " << message;
});
connect(&websocketClient, &QWebSocket::binaryMessageReceived, this, [=](const QByteArray& byteArray) {
LOG() << "webSocket 收到二进制的消息" << byteArray.length();
//TODO
});
//和服务器真正建立连接
websocketClient.open(WEBSOCKET_URL);
}
void NetClient::sendAuth()
{
bite_im::ClientAuthenticationReq req;
req.setRequestId(makeRequestId());
req.setSessionId(dataCenter->getLoginSessionId());
QByteArray body = req.serialize(&serializer);
websocketClient.sendBinaryMessage(body);
LOG() << "[WS身份认证] requestId= " << req.requestId() << ",loginSessionId= " << req.sessionId();
}
QString NetClient::makeRequestId()
{
//基本的要求确保每个请求的Id都是不重复的唯一的
//通过UUID实现上述的效果
return "R" + QUuid::createUuid().toString().sliced(25, 12);
}
//通过这个函数把发送HTTP请求的操作封装一下
QNetworkReply* NetClient::sendHttpRequest(const QString& apiPath, const QByteArray& body)
{
//构造出HTTP请求
QNetworkRequest httpReq;
httpReq.setUrl(QUrl(HTTP_URL + apiPath));
httpReq.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-protobuf");
//发起HTTP请求
QNetworkReply* httpResp = httpClient.post(httpReq, body);
return httpResp;
}
//在这个函数内部,完成具体的网络通信即可
void NetClient::getMyself(const QString& loginSessionId)
{
//构造出HTTP请求body部分
bite_im::GetUserInfoReq req;
req.setRequestId(makeRequestId());
req.setSessionId(loginSessionId);
QByteArray body = req.serialize(&serializer);
LOG() << "获取个人信息->发送请求: requestId=" << req.requestId() << ", loginSessionId=" << loginSessionId;
//构造出HTTP请求
QNetworkReply* httpResp = sendHttpRequest("/service/user/get_user_info", body);
//通过信号槽,获取到当前的响应
connect(httpResp, &QNetworkReply::finished, this, [=]() {
//if (httpResp->error() != QNetworkReply::NoError) {
// //说明HTTP请求出错了
// LOG() << "HTTP error: " << httpResp->errorString();
// httpResp->deleteLater();
// return;
//}
////说明拿到了body
//QByteArray respBody = httpResp->readAll();
////针对body进行反序列化,解析成对象
//bite_im::GetUserInfoRsp respObj;
//respObj.deserialize(&serializer, respBody);
////判定一下业务上是否出错
//if (!respObj.success()) {
// LOG() << "requestId= " << respObj.requestId() << ", errmsg=" << respObj.errmsg();
// httpResp->deleteLater();
// return;
//}
//继续处理后续的业务逻辑
//获取http回复
bool ok = false;
QString reason;
auto resp = handleHttpResponse<bite_im::GetUserInfoRsp>(httpResp, &ok, &reason);
//判定响应是否正确
if (!ok) {
LOG() << "获取个人信息->出错 requestId= " << req.requestId() << ", reason= " << reason;
return;
}
//把响应的数据保存到DataCenter
dataCenter->resetMyself(resp);
//通知调用逻辑,响应已经处理完成了,仍然通过信号槽通知
emit dataCenter->getMyselfDone();
//打印日志
LOG() << "获取个人信息->响应处理完毕 requestId" << req.requestId();
});
}
void NetClient::getFriendList(const QString& loginSessionId)
{
//通过protobuf构造body
bite_im::GetFriendListReq req;
req.setRequestId(makeRequestId());
req.setSessionId(loginSessionId);
QByteArray body = req.serialize(&serializer);
LOG() << "获取好友列表->发送请求 requestId=" << req.requestId() << ", loginSessionId= " << loginSessionId;
//发送HTTP请求
QNetworkReply* httpResp = this->sendHttpRequest("/service/friend/get_friend_list", body);
//处理响应
connect(httpResp, &QNetworkReply::finished, this, [=]() {
//解析响应
bool ok = false;
QString reason;
auto friendListResp = this->handleHttpResponse<bite_im::GetFriendListRsp>(httpResp, &ok, &reason);
if (!ok) {
LOG() << "获取好友列表->失败 requestId= " << req.requestId() << ", reason= " << reason;
}
LOG() << "获取好友列表->成功";
//把结果保存在DataCenter中
dataCenter->resetFriendList(friendListResp);
// 发送信号
emit dataCenter->getFriendListDone();
});
}
void NetClient::getChatSessionList(const QString& loginSessionId)
{
//通过protobuf构造body
bite_im::GetChatSessionListReq req;
req.setRequestId(makeRequestId());
req.setSessionId(loginSessionId);
QByteArray body = req.serialize(&serializer);
LOG() << "获取会话列表->发送请求 requestId= " << req.requestId() << ", loginSessionId= " << loginSessionId;
//发送HTTP请求
QNetworkReply* resp = this->sendHttpRequest("/service/friend/get_chat_session_list", body);
//针对响应进行处理
connect(resp, &QNetworkReply::finished, this, [=]() {
//解析响应
bool ok = false;
QString reason;
auto pbResp = this->handleHttpResponse<bite_im::GetChatSessionListRsp>(resp, &ok, &reason);
//判断响应是否正确
if (!ok) {
LOG() << "获取会话列表->失败 reason= " << reason;
return;
}
//到这里说明没有问题把得到的数据写入到DataCenter中
dataCenter->resetChatSessionList(pbResp);
//通知调用者,响应已经处理完毕了
emit dataCenter->getChatSessionListDone();
//打印日志
LOG() << "获取会话列表->处理响应完毕 requestId= " << pbResp->requestId();
});
}
void NetClient::getApplyList(const QString& loginSessionId)
{
//通过protobuf构造body
bite_im::GetPendingFriendEventListReq req;
req.setRequestId(makeRequestId());
req.setSessionId(loginSessionId);
QByteArray body = req.serialize(&serializer);
LOG() << "获取好友申请列表->发送请求 reason= " << req.requestId() << ", loginSessonId= " << loginSessionId;
//发送HTTP请求
QNetworkReply* resp = this->sendHttpRequest("/service/friend/get_pending_friend_events", body);
//处理响应
connect(resp, &QNetworkReply::finished, this, [=]() {
//解析响应
bool ok = false;
QString reason;
auto pbResp = this->handleHttpResponse<bite_im::GetPendingFriendEventListRsp>(resp, &ok, &reason);
//判定结果是否正确
if (!ok) {
LOG() << "获取好友申请列表->失败 reason= " << reason;
return;
}
//拿到的数据写入到DataCenter中
dataCenter->resetApplyList(pbResp);
//发送信号通知界面,已经处理完毕
emit dataCenter->getApplyListDone();
LOG() << "获取好友申请列表->处理响应完成 requestId= " << req.requestId();
});
}
void NetClient::getRecentMessageList(const QString& loginSessionId, const QString& chatSessionId)
{
//通过protobuf构造请求body
bite_im::GetRecentMsgReq req;
req.setRequestId(makeRequestId());
req.setChatSessionId(chatSessionId);
req.setMsgCount(50);
req.setSessionId(loginSessionId);
QByteArray body = req.serialize(&serializer);
LOG() << "获取最近消息->发送请求 requestId= " << req.requestId() << ", loginSessionId= " << loginSessionId;
//发送http请求
QNetworkReply* resp = this->sendHttpRequest("/service/message_storage/get_recent", body);
//处理响应
connect(resp, &QNetworkReply::finished, this, [=]() {
//解析响应,反序列化
bool ok = false;
QString reason;
auto pbResp = this->handleHttpResponse<bite_im::GetRecentMsgRsp>(resp, &ok, &reason);
//判定响应是否出错
if (!ok) {
LOG() << "获取最近消息->失败 reason= " << reason;
return;
}
//把拿到的数据设置到DataCenter中
dataCenter->resetRecentMessageList(chatSessionId, pbResp);
//发送信号,告知界面进行更新
emit dataCenter->getRecentMessageListDone(chatSessionId);
});
}
} //end namespace network