#pragma once #include #include #include #include #include #include #include "../model/data.h" //此处为了避免“循环包含”的问题,就需要使用前置声明的方法 // 代替包含头文件 namespace model { class DataCenter; } //end namespace model class model::DataCenter; namespace network { class NetClient : public QObject { Q_OBJECT private: //定义重要的常量,ip暂时使用本地的回环ip,端口号暂定的8000和8001 const QString HTTP_URL = "http://127.0.0.1:8000"; const QString WEBSOCKET_URL = "ws://127.0.0.1:8001/ws"; public: NetClient(model::DataCenter* dataCenter); //验证网络的联通性 void ping(); //初始化websocket void initWebSocket(); //发送身份认证请求 void sendAuth(); //生成请求的Id static QString makeRequestId(); //封装发送请求的逻辑 QNetworkReply* sendHttpRequest(const QString& apiPath, const QByteArray& body); //封装处理响应的逻辑(判定HTTP正确性,反序列化,判断业务的正确性) //由于不同的api返回的pb对象结构不同,为了让一个函数能够处理多种不同的类型,需要使用模板 //后面两个是输出型参数,用于表示这次的操作是成功还是失败 template std::shared_ptr handleHttpResponse(QNetworkReply* httpResp, bool* ok, QString* reason) { //判定HTTP层面上 if (httpResp->error() != QNetworkReply::NoError) { *ok = false; *reason = httpResp->errorString(); httpResp->deleteLater(); return std::shared_ptr(); } //说明并没有出错, 那就获取到响应的body QByteArray respBody = httpResp->readAll(); //针对body反序列化 std::shared_ptr respObj = std::make_shared(); respObj->deserialize(&serializer, respBody); //判定业务的结构是否正确 if (!respObj->success()) { *ok = false; *reason = respObj->errmsg(); httpResp->deleteLater(); return std::shared_ptr(); } //释放httpResp对象 httpResp->deleteLater(); return respObj; } void getMyself(const QString& loginSessionId); private: model::DataCenter* dataCenter; //http客户端 QNetworkAccessManager httpClient; //websocket客户端 QWebSocket websocketClient; //序列化器 QProtobufSerializer serializer; signals: }; } //end namespace network