1. LibCurl的简单介绍
libcurl是一个优秀的网络请求库,其主要功能是用不同的协议连接和沟通不同的服务器,支持http, https, ftp, gopher, telnet, dict, file, 和ldap 协议,同时也支持HTTPS证书授权,HTTP POST, HTTP PUT, FTP 上传,HTTP基本表单上传,代理,cookies,和用户认证。
2. LibCurl的编译
见我的另一篇博客:https://blog.csdn.net/linyibin_123/article/details/127574012
3. 使用LibCurl封装SDK库
采用工厂模式,类LibCurlSdk实现了公有的日志操作功能,LibCurlSdkHttp类和LibCurlSdkFTP继承于LibCurlSdk,分别实现http操作功能和ftp操作功能。同时为了不对外暴露实际的功能代码,类LibCurlSdkHttp和类LibCurlSdkFTP使用纯虚函数,即类LibCurlSdkHttp和类LibCurlSdkFTP为抽象类,实际功能由其子类HttpSdk和FtpSdk进行实现。类LibCurlSdkHttp和类LibCurlSdkFTP均支持单例模式,类LibCurlSdkHttp的SendHttpGet和SendHttpPost接口可供调用者使用自定义的url进行请求,SdkAddJob接口可让调用者根据枚举项选择某个功能进行请求,该请求会在线程池中执行。
3.1 核心代码:
libcurlsdk.h
/**************************************************************************
Copyright:My LibCurlSdk
Author: ybLin
Date:2022-11-08
Description: LibCurl SDK
**************************************************************************/
#ifndef LIBCURLSDK_H
#define LIBCURLSDK_H
#include <QObject>
#include "libcurlsdk_global.h"
//Log Level
typedef enum SDK_LOG_LEVEL
{
LOG_LEVEL_DEBUG = 0,
LOG_LEVEL_INFO,
LOG_LEVEL_WARN,
LOG_LEVEL_CRITICAL,
LOG_LEVEL_FATAL
}SDK_LOG_LEVEL_E;
//Content-Type
typedef enum SDK_CONTENT_TYPE
{
CONTENT_TYPE_TEXT_HTML = 0,//HTML格式
CONTENT_TYPE_TEXT_PLAIN,//纯文本格式
CONTENT_TYPE_TEXT_XML,//XML格式
CONTENT_TYPE_IMAGE_GIF,//gif图片格式
CONTENT_TYPE_IMAGE_JPEG,//jpg图片格式
CONTENT_TYPE_IMAGE_PNG,//png图片格式
CONTENT_TYPE_APPLICATION_XHTML_XML,//XHTML格式
CONTENT_TYPE_APPLICATION_XML,//XML数据格式
CONTENT_TYPE_APPLICATION_ATOM_XML,//Atom XML聚合格式
CONTENT_TYPE_APPLICATION_JSON,//JSON数据格式
CONTENT_TYPE_APPLICATION_PDF,//pdf格式
CONTENT_TYPE_APPLICATION_MSWORD,//Word文档格式
CONTENT_TYPE_APPLICATION_OCTET_STREAM,//二进制流数据
CONTENT_TYPE_APPLICATION_X_WWW_FORM_URLENCODED,//表单默认的提交数据的格式
CONTENT_TYPE_MULTIPART_FORM_DATA//需要在表单中进行文件上传时,就需要使用该格式
}SDK_CONTENT_TYPE_T;
typedef struct
{
char sIP[64];
int nPort;
char sUserName[64];
char sPassword[32];
}SDK_USER_INFO_T;
typedef enum SDK_API_TYPE
{
API_TYPE_SET_BRIGHTNESS = 0,
API_TYPE_GET_BRIGHTNESS,
API_TYPE_SET_IMAGEPARAMS,
API_TYPE_GET_IMAGEPARAMS,
API_TYPE_SET_TESTPARAM,
API_TYPE_GET_TESTPARAM,
API_TYPE_HTTP_MAX
}SDK_API_TYPE_E;
typedef struct
{
int nBrightness;
int nContrast;
int nSaturation;
int nSharpness;
int nFLevel;
}IMAGE_SETTINGS_T;
///
/// \brief The LibCurlSdk class
///Common
class LIBCURLSDKSHARED_EXPORT LibCurlSdk
{
public:
LibCurlSdk();
//Log
void setLogSave(bool bSave, QString sPath = "");
void setLogLevel(SDK_LOG_LEVEL_E nLevel);
};
//Http
class LIBCURLSDKSHARED_EXPORT LibCurlSdkHttp : public QObject, public LibCurlSdk
{
Q_OBJECT
public:
LibCurlSdkHttp();
static LibCurlSdkHttp& getInstance();
//Get Common API
virtual int SendHttpGet(const QString sUrl, QString& sResponse) = 0;
//Post Common API
virtual int SendHttpPost(const QString sUrl, const QString sParam, const QString sHead, QString& sResponse) = 0;
virtual int SendHttpPost(const QString sUrl, const QString sParam, SDK_CONTENT_TYPE_T nHead, QString& sResponse) = 0;
//Api in Thread
virtual void SdkAddJob(SDK_USER_INFO_T stUser, SDK_API_TYPE_E eCmd, void *IpcParam) = 0;
signals:
void sig_HttpJobReturn(SDK_USER_INFO_T stUser, int eCmd, void* IpcParam, bool bSucc);
};
//Ftp 暂未实现
class LIBCURLSDKSHARED_EXPORT LibCurlSdkFTP : public QObject, public LibCurlSdk
{
public:
LibCurlSdkFTP();
static LibCurlSdkFTP& getInstance();
virtual int UploadFtp(const QString sIP, const quint16 nPort, QString& sResponse) = 0;
virtual int DownLoadFtp(const QString sIP, const quint16 nPort, QString& sResponse) = 0;
};
#endif // LIBCURLSDK_H
libcurlsdk.cpp
#include "libcurlsdk.h"
#include "httpsdk.h"
#include "ftpsdk.h"
#include "runlog.h"
#include <QDebug>
LibCurlSdk::LibCurlSdk()
{
}
/***************************
* Log Config
* *************************/
void LibCurlSdk::setLogSave(bool bSave, QString sPath)
{
qDebug() << __FUNCTION__ << " sPath:" << sPath;
if(bSave)
{
RunLog::Instance()->start(sPath);
}
else
{
RunLog::Instance()->stop();
}
}
void LibCurlSdk::setLogLevel(SDK_LOG_LEVEL_E nLevel)
{
qDebug() << __FUNCTION__ << " nLevel:" << nLevel;
RunLog::Instance()->setLogLevel(RunLog::LOG_LEVEL(nLevel));
}
/***************************
* Http
* *************************/
LibCurlSdkHttp::LibCurlSdkHttp()
{
//qRegisterMetaType<SDK_USER_INFO_T>("SDK_USER_INFO_T");
}
LibCurlSdkHttp &LibCurlSdkHttp::getInstance()
{
static HttpSdk s_obj;
return s_obj;
}
/***************************
* Ftp
* *************************/
LibCurlSdkFTP::LibCurlSdkFTP()
{
}
LibCurlSdkFTP &LibCurlSdkFTP::getInstance()
{
static FtpSdk s_obj;
return s_obj;
}
httpsdk.h
#ifndef HTTPSDK_H
#define HTTPSDK_H
#include "libcurlsdk.h"
#include "sdkthread.h"
#define MAX_BUF_SIZE_8 8
#define MAX_BUF_SIZE_16 16
#define MAX_BUF_SIZE_32 32
#define MAX_BUF_SIZE_64 64
#define MAX_BUF_SIZE_96 96
#define MAX_BUF_SIZE_128 128
#define MAX_BUF_SIZE_256 256
#define MAX_BUF_SIZE_512 512
#define MAX_BUF_SIZE_1024 1024
#define MAX_BUF_SIZE_2048 2048
#define MAX_BUF_SIZE_4096 4096
#define SEP_STRING "\n"
class HttpSdk : public LibCurlSdkHttp
{
public:
HttpSdk();
static HttpSdk& getInstance();
//Api Run In Thread
void SdkAddJob(SDK_USER_INFO_T stUser, SDK_API_TYPE_E eCmd, void *IpcParam);
//Get
//Get Common API
int SendHttpGet(const QString sUrl, QString& sResponse);
//Get Proper API
int setBrightness(SDK_USER_INFO_T stUser, void* pParam);
int getBrightness(SDK_USER_INFO_T stUser, void* pParam);
int setImageParams(SDK_USER_INFO_T stUser, void* pParam);
int getImageParams(SDK_USER_INFO_T stUser, void* pParam);
//Post Common API
int SendHttpPost(const QString sUrl, const QString sParam, const QString sHead, QString& sResponse);
int SendHttpPost(const QString sUrl, const QString sParam, SDK_CONTENT_TYPE_T nHead, QString& sResponse);
//Post Proper API
int setTestParam(SDK_USER_INFO_T stUser, void* pParam);
int getTestParam(SDK_USER_INFO_T stUser, void* pParam);
private:
QString m_sUser;
QString m_sPwd;
SDKThread *m_sdkT;
};
#endif // HTTPSDK_H
httpsdk.cpp
#include "httpsdk.h"
#include "curlsdk.h"
#include "runlog.h"
#include <QDateTime>
#include <QJsonParseError>
#include <QJsonObject>
/
/**********************************
* Common API
* ********************************/
static int MySscanf(const char *pText, const char *pRegExp, const char sSep[1],
char *pResult, int nResultLen)
{
int i = 0;
size_t nStart = strlen(pRegExp);
const char *pStr = strstr(pText, pRegExp);
if(!pStr)
return -1;
for(; i < (int)strlen(pStr); i++)
{
if(pStr[nStart+i] == sSep[0])
break;
if(i+1 > nResultLen)
break;
pResult[i] = pStr[nStart+i];
}
pResult[i] = '\0';
return i;
}
int GetResponseVal(QString sKey, const char *pResponse, char *pVal, int nValLen)
{
QByteArray ba = sKey.toLatin1();
char *pCh = ba.data();
char sFilter[MAX_BUF_SIZE_128] = {0};
snprintf(sFilter, sizeof(sFilter), "OK %s=", pCh);
if(MySscanf(pResponse, sFilter, SEP_STRING, pVal, nValLen) != -1)
{
return 0;
}
else
{
return -1;
}
}
void GetResponseIntVal(QString skey, const char *pResponse, int *pVal)
{
QByteArray ba = skey.toLatin1();
char *ch = ba.data();
char sVal[MAX_BUF_SIZE_4096] = {0};
char sFilter[MAX_BUF_SIZE_128] = {0};
snprintf(sFilter, sizeof(sFilter), "OK %s=", ch);
if(MySscanf(pResponse, sFilter, SEP_STRING, sVal, sizeof(sVal)) != -1)
{
*pVal = atoi(sVal);
}
}
QString GetContentType(SDK_CONTENT_TYPE_T nHead)
{
QString sContentType;
switch(nHead)
{
case CONTENT_TYPE_TEXT_HTML:
sContentType = "Content-type:text/html";
break;
case CONTENT_TYPE_TEXT_PLAIN:
sContentType = "Content-type:text/plain";
break;
case CONTENT_TYPE_TEXT_XML:
sContentType = "Content-type:text/xml";
break;
case CONTENT_TYPE_IMAGE_GIF:
sContentType = "Content-type:image/gif";
break;
case CONTENT_TYPE_IMAGE_JPEG:
sContentType = "Content-type:image/jpeg";
break;
case CONTENT_TYPE_IMAGE_PNG:
sContentType = "Content-type:image/png";
break;
case CONTENT_TYPE_APPLICATION_XHTML_XML:
sContentType = "Content-type:application/xhtml+xml";
break;
case CONTENT_TYPE_APPLICATION_XML:
sContentType = "Content-type:application/xml";
break;
case CONTENT_TYPE_APPLICATION_ATOM_XML:
sContentType = "Content-type:application/atom+xml";
break;
case CONTENT_TYPE_APPLICATION_JSON:
sContentType = "Content-type:application/json";
break;
case CONTENT_TYPE_APPLICATION_PDF:
sContentType = "Content-type:application/pdf";
break;
case CONTENT_TYPE_APPLICATION_MSWORD:
sContentType = "Content-type:application/msword";
break;
case CONTENT_TYPE_APPLICATION_OCTET_STREAM:
sContentType = "Content-type:application/octet-stream";
break;
case CONTENT_TYPE_APPLICATION_X_WWW_FORM_URLENCODED:
sContentType = "Content-type:application/x-www-form-urlencoded";
break;
case CONTENT_TYPE_MULTIPART_FORM_DATA:
sContentType = "Content-type:multipart/form-data";
break;
default:
sContentType = "Content-type:text/plain";
break;
}
return sContentType;
}
///
HttpSdk::HttpSdk() :
m_sUser("admin"),m_sPwd("123456")
{
m_sdkT = &SDKThread::instance();
}
HttpSdk &HttpSdk::getInstance()
{
static HttpSdk s_obj;
return s_obj;
}
/**********************************
* Http:
* Api Run In Thread
* ********************************/
void HttpSdk::SdkAddJob(SDK_USER_INFO_T stUser, SDK_API_TYPE_E eCmd, void *IpcParam)
{
m_sdkT->SDKAddJob(stUser, eCmd, IpcParam);
}
/**********************************
* Http:
* Get Common API
* URL:http://127.0.0.1:8080/my.rq?setbrightnessval=50
* http://127.0.0.1:8080/my.rq?getparam=brightnessval
* ********************************/
int HttpSdk::SendHttpGet(const QString sUrl, QString &sResponse)
{
string strResponse;
if(CurlSdk::getInstance().HttpGet(sUrl.toStdString(), strResponse) == 0)
{
sResponse = QString::fromStdString(strResponse);
qDebug() << "sResponse:" << sResponse;
if(sResponse.contains("OK"))
{
QString msg = QString("Current Time: %1 Http Send:%2 Success.") \
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss:zzz")) \
.arg(sUrl);
qInfo() << msg;
return 0;
}
}
QString msg = QString("Current Time: %1 Http Send:%2 Fail.") \
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss:zzz")) \
.arg(sUrl);
qWarning() << msg;
return -1;
}
/**********************************
* Http:
* Set Brightness (Get)
* ********************************/
int HttpSdk::setBrightness(SDK_USER_INFO_T stUser, void* pParam)
{
int *nVal = (int*)pParam;
QString sUrl;
if(strlen(stUser.sUserName) == 0 || strlen(stUser.sPassword) == 0)
{
sUrl = QString("http://%1:%2/my.rq?module=imageconf&setbrightnessval=%5")\
.arg(stUser.sIP).arg(stUser.nPort).arg(*nVal);
}
else
{
sUrl = QString("http://%1:%2@%3:%4/my.rq?module=imageconf&setbrightnessval=%5").arg(stUser.sUserName)\
.arg(stUser.sPassword).arg(stUser.sIP).arg(stUser.nPort).arg(*nVal);
}
QString sResponse;
return SendHttpGet(sUrl, sResponse);
}
/**********************************
* Http:
* Get Brightness (Get)
* ********************************/
int HttpSdk::getBrightness(SDK_USER_INFO_T stUser, void* pParam)
{
int *nVal = (int*)pParam;
QString sUrl;
if(strlen(stUser.sUserName) == 0 || strlen(stUser.sPassword) == 0)
{
sUrl = QString("http://%1:%2/my.rq?getparam=brightnessval")\
.arg(stUser.sIP).arg(stUser.nPort);
}
else
{
sUrl = QString("http://%1:%2@%3:%4/my.rq?getparam=brightnessval").arg(stUser.sUserName).arg(stUser.sPassword)\
.arg(stUser.sIP).arg(stUser.nPort);
}
const QString sKey = "brightnessval";
QString sResponse;
char strResVal[MAX_BUF_SIZE_512];
if(SendHttpGet(sUrl, sResponse) == 0)
{
std::string strResponse = sResponse.toStdString();
if(GetResponseVal(sKey, strResponse.data(), strResVal, sizeof(strResVal)) == 0)
{
*nVal = QString(QLatin1String(strResVal)).toInt();
return 0;
}
}
return -1;
}
/**********************************
* Http:
* Set Image Params (Get)
* ********************************/
int HttpSdk::setImageParams(SDK_USER_INFO_T stUser, void *pParam)
{
IMAGE_SETTINGS_T *pImageParam = (IMAGE_SETTINGS_T *)pParam;
if(pImageParam == nullptr)
return -1;
QString sUrl;
if(strlen(stUser.sUserName) == 0 || strlen(stUser.sPassword) == 0)
{
sUrl = QString("http://%1:%2/my.rq?module=imageconf&setbrightnessval=%5&setcontrastval=%6&setsaturationval=%7&setsharpnessval=%8&setnflevelval=%9")\
.arg(stUser.sIP).arg(stUser.nPort).arg(pImageParam->nBrightness)\
.arg(pImageParam->nContrast).arg(pImageParam->nSaturation)\
.arg(pImageParam->nSharpness).arg(pImageParam->nFLevel);
}
else
{
sUrl = QString("http://%1:%2@%3:%4/my.rq?module=imageconf&setbrightnessval=%5&setcontrastval=%6&setsaturationval=%7&setsharpnessval=%8&setnflevelval=%9")\
.arg(stUser.sUserName).arg(stUser.sPassword).arg(stUser.sIP) \
.arg(stUser.nPort).arg(pImageParam->nBrightness)\
.arg(pImageParam->nContrast).arg(pImageParam->nSaturation)\
.arg(pImageParam->nSharpness).arg(pImageParam->nFLevel);
}
QString sResponse;
return SendHttpGet(sUrl, sResponse);
}
/**********************************
* Http:
* Get Image Params (Get)
* ********************************/
int HttpSdk::getImageParams(SDK_USER_INFO_T stUser, void *pParam)
{
IMAGE_SETTINGS_T *pImageParam = (IMAGE_SETTINGS_T *)pParam;
if(!pImageParam)
return -1;
QString sUrl;
if(strlen(stUser.sUserName) == 0 || strlen(stUser.sPassword) == 0)
{
sUrl = QString("http://%1:%2/my.rq?getparam=brightnessval&getparam=contrastval&getparam=saturationval"\
"&getparam=sharpnessval&getparam=nflevelval")\
.arg(stUser.sIP).arg(stUser.nPort);
}
else
{
sUrl = QString("http://%1:%2@%3:%4/my.rq?getparam=brightnessval&getparam=contrastval&getparam=saturationval"\
"&getparam=sharpnessval&getparam=nflevelval")\
.arg(stUser.sUserName).arg(stUser.sPassword).arg(stUser.sIP).arg(stUser.nPort);
}
const QString sKey = "brightnessval";
QString sResponse;
int nValue;
if(SendHttpGet(sUrl, sResponse) == 0)
{
std::string strResponse = sResponse.toStdString();
GetResponseIntVal("brightnessval", strResponse.data(), &nValue);
pImageParam->nBrightness = nValue;
GetResponseIntVal("contrastval", strResponse.data(), &nValue);
pImageParam->nContrast = nValue;
GetResponseIntVal("saturationval", strResponse.data(), &nValue);
pImageParam->nSaturation = nValue;
GetResponseIntVal("sharpnessval", strResponse.data(), &nValue);
pImageParam->nSharpness = nValue;
GetResponseIntVal("nflevelval", strResponse.data(), &nValue);
pImageParam->nFLevel = nValue;
return 0;
}
return -1;
}
/**********************************
* Http:
* Post Common API
* Url:http://127.0.0.1:8080
* Param:/setparam=50
* /getparam=testparam
* Header:Content-type:application/json
* ********************************/
int HttpSdk::SendHttpPost(const QString sUrl, const QString sParam, const QString sHead, QString& sResponse)
{
string strResponse;
if(CurlSdk::getInstance().HttpPost(sUrl.toStdString(), sParam.toStdString(), sHead.toStdString(), strResponse) == 0)
{
sResponse = QString::fromStdString(strResponse);
return 0;
}
return -1;
}
int HttpSdk::SendHttpPost(const QString sUrl, const QString sParam, SDK_CONTENT_TYPE_T nHead, QString &sResponse)
{
QString sHead = GetContentType(nHead);
string strResponse;
if(CurlSdk::getInstance().HttpPost(sUrl.toStdString(), sParam.toStdString(), sHead.toStdString(), strResponse) == 0)
{
sResponse = QString::fromStdString(strResponse);
return 0;
}
return -1;
}
/**********************************
* Http:
* Set Test Param (Post)
* ********************************/
int HttpSdk::setTestParam(SDK_USER_INFO_T stUser, void *pParam)
{
QString sHead = GetContentType(CONTENT_TYPE_APPLICATION_JSON);
string strResponse;
int *nVal = (int*)pParam;
QString sUrl = QString("http://%1:%2").arg(stUser.sIP).arg(stUser.nPort);
QString sParam = QString("/setparam=%1").arg(*nVal);
if(CurlSdk::getInstance().HttpPost(sUrl.toStdString(), sParam.toStdString(), sHead.toStdString(), strResponse) == 0)
{
return 0;
}
return -1;
}
/**********************************
* Http:
* Get Test Param (Post)
* ********************************/
int HttpSdk::getTestParam(SDK_USER_INFO_T stUser, void *pParam)
{
int *pVal = (int*)pParam;
QString sHead = GetContentType(CONTENT_TYPE_APPLICATION_JSON);
string strResponse;
QString sUrl = QString("http://%1:%2").arg(stUser.sIP).arg(stUser.nPort);
QString sParam = "/getparam=testparam";
QString sResponse;
const QString sKey = "param";
if(CurlSdk::getInstance().HttpPost(sUrl.toStdString(), sParam.toStdString(), sHead.toStdString(), strResponse) == 0)
{
sResponse = QString::fromStdString(strResponse);
QByteArray byteArray = sResponse.toLatin1();
QJsonParseError jsonError;
// 转化为 JSON 文档
QJsonDocument doucment = QJsonDocument::fromJson(byteArray, &jsonError);
// 解析未发生错误
if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError))
{
if (doucment.isObject())
{
// JSON 文档为对象
QJsonObject object = doucment.object(); // 转化为对象
if (object.contains("param"))
{ // 包含指定的 key
QJsonValue value = object.value("param"); // 获取指定 key 对应的 value
if (value.isDouble())
{
int nVal = value.toVariant().toInt();
qDebug() << "Param : " << nVal;
*pVal = nVal;
return 0;
}
}
}
}
}
return -1;
}
sdkthread.h
/**************************************************************************
Copyright:IVS Camera
Author: ybLin
Date:2022-11-8
Description:SDK Thread
**************************************************************************/
#ifndef SDKTHREAD_H
#define SDKTHREAD_H
#include <QObject>
#include "sdktask.h"
class SDKThread : public QObject
{
public:
static SDKThread& instance();
virtual ~SDKThread();
SDKTask *m_psdktaskT;
void SDKAddJob(SDK_USER_INFO_T stUser, int eCmd, void* IpcParam);
private:
explicit SDKThread(QObject *parent = nullptr);
};
#endif // SDKTHREAD_H
sdkthread.cpp
/**************************************************************************
Copyright:My LibCurlSdk
Author: ybLin
Date:2022-11-8
Description:Thread Function
**************************************************************************/
#include "sdkthread.h"
#include <QThreadPool>
SDKThread::SDKThread(QObject *parent) : QObject(parent)
{
QThreadPool::globalInstance()->setMaxThreadCount(128);
}
SDKThread &SDKThread::instance()
{
static SDKThread s_obj;
return s_obj;
}
SDKThread::~SDKThread()
{
}
void SDKThread::SDKAddJob(SDK_USER_INFO_T stUser, int eCmd, void *IpcParam)
{
m_psdktaskT = new SDKTask(nullptr, eCmd, IpcParam, stUser);
if(m_psdktaskT)
{
QThreadPool::globalInstance()->start(m_psdktaskT);
}
}
sdktask.h
#ifndef SDKTASK_H
#define SDKTASK_H
#include <QObject>
#include <QMutex>
#include <QRunnable>
#include "libcurlsdk.h"
//QT_FORWARD_DECLARE_CLASS(SDKThread)
class SDKTask: public QObject, public QRunnable
{
Q_OBJECT
public:
SDKTask(QObject *parent, int eCmd, void *param, SDK_USER_INFO_T& stUser);
virtual ~SDKTask();
void run();
private:
int m_nCmd;
void* m_pParam;
SDK_USER_INFO_T m_stUser;
signals:
void sig_httptaskreturn(SDK_USER_INFO_T pUser, int eCmd, void* IpcParam, bool bSucc);
};
#endif // SDKTASK_H
sdktask.cpp
#include "sdktask.h"
#include "httpsdk.h"
#include <QDebug>
SDKTask::SDKTask(QObject *parent, int eCmd, void *param, SDK_USER_INFO_T& stUser)
: QObject(parent),
m_nCmd(eCmd), m_pParam(param), m_stUser(stUser)
{
this->setAutoDelete(true);
connect(this, SIGNAL(sig_httptaskreturn(SDK_USER_INFO_T, int, void*, bool)),&LibCurlSdkHttp::getInstance(),
SIGNAL(sig_HttpJobReturn(SDK_USER_INFO_T, int, void*, bool)) );
}
SDKTask::~SDKTask()
{
}
void SDKTask::run()
{
int ret = 0;
switch(m_nCmd)
{
case API_TYPE_SET_BRIGHTNESS:
ret = HttpSdk::getInstance().setBrightness(m_stUser, m_pParam);
break;
case API_TYPE_GET_BRIGHTNESS:
ret = HttpSdk::getInstance().getBrightness(m_stUser, m_pParam);
break;
case API_TYPE_SET_IMAGEPARAMS:
ret = HttpSdk::getInstance().setImageParams(m_stUser, m_pParam);
break;
case API_TYPE_GET_IMAGEPARAMS:
ret = HttpSdk::getInstance().getImageParams(m_stUser, m_pParam);
break;
case API_TYPE_SET_TESTPARAM:
ret = HttpSdk::getInstance().setTestParam(m_stUser, m_pParam);
break;
case API_TYPE_GET_TESTPARAM:
ret = HttpSdk::getInstance().getTestParam(m_stUser, m_pParam);
break;
}
if(m_nCmd >= API_TYPE_SET_BRIGHTNESS && m_nCmd <= API_TYPE_HTTP_MAX)
{
if(ret == 0)
emit sig_httptaskreturn(m_stUser, m_nCmd, m_pParam, true);
else
emit sig_httptaskreturn(m_stUser, m_nCmd, m_pParam, false);
}
}
curlsdk.h
#ifndef CURLSDK_H
#define CURLSDK_H
#include <QMutex>
#include "curl.h"
#include "commondef.h"
using namespace std;
class CurlSdk
{
public:
CurlSdk();
virtual ~CurlSdk();
static CurlSdk& getInstance();
//Http Get请求
int HttpGet(const string& strUrl, string& strResponse);
//Http Post请求
int HttpPost(const string& strUrl, const string& strPost, const string& sHeader, string& strResponse);
void SetDebug(bool bDebug);
private:
bool m_bDebug;
QMutex m_lock;
};
#endif // CURLSDK_H
curlsdk.cpp
#include "curlsdk.h"
CurlSdk::CurlSdk()
{
m_bDebug = false;
CURLcode res = curl_global_init(CURL_GLOBAL_ALL);
if(CURLE_OK != res)
{
MY_DEBUG << "CurSdk curl_global_init Failed.";
}
}
CurlSdk::~CurlSdk()
{
curl_global_cleanup();
}
CurlSdk &CurlSdk::getInstance()
{
static CurlSdk s_obj;
return s_obj;
}
static size_t onWriteFunc(char *pData, size_t size, size_t nmemb, string* pWriteData)
{
if(nullptr == pWriteData)
return 0;
size_t len = size * nmemb;
pWriteData->append(pData, len);
return len;
}
static int OnDebug(CURL *, curl_infotype itype, char * pData, size_t size, void *)
{
Q_UNUSED(size);
if(itype == CURLINFO_TEXT)
{
MY_DEBUG << "[TEXT]:" << pData;
}
else if(itype == CURLINFO_HEADER_IN)
{
MY_DEBUG << "[HEADER_IN]:" << pData;
}
else if(itype == CURLINFO_HEADER_OUT)
{
MY_DEBUG << "[HEADER_OUT]:" << pData;
}
else if(itype == CURLINFO_DATA_IN)
{
MY_DEBUG << "[DATA_IN]:" << pData;
}
else if(itype == CURLINFO_DATA_OUT)
{
MY_DEBUG << "[DATA_OUT]:" << pData;
}
return 0;
}
int CurlSdk::HttpGet(const string& strUrl, string& strResponse)
{
CURLcode res;
CURL* pCurl = curl_easy_init();
if(nullptr == pCurl)
{
return CURLE_FAILED_INIT;
}
if(m_bDebug)
{
curl_easy_setopt(pCurl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(pCurl, CURLOPT_DEBUGFUNCTION, OnDebug);
}
curl_easy_setopt(pCurl, CURLOPT_URL, strUrl.c_str());
curl_easy_setopt(pCurl, CURLOPT_READFUNCTION, NULL);
curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, onWriteFunc);
curl_easy_setopt(pCurl, CURLOPT_WRITEDATA, static_cast<void*>(&strResponse));
curl_easy_setopt(pCurl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);//开启digest认证
//当多个线程都使用超时处理的时候,同时主线程中有sleep或是wait等操作。
//如果不设置这个选项,libcurl将会发信号打断这个wait从而导致程序退出。
curl_easy_setopt(pCurl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(pCurl, CURLOPT_CONNECTTIMEOUT, 3);
curl_easy_setopt(pCurl, CURLOPT_TIMEOUT, 3);
res = curl_easy_perform(pCurl);
curl_easy_cleanup(pCurl);
return res;
}
int CurlSdk::HttpPost(const string& strUrl, const string& strPost, const string &sHeader, string& strResponse)
{
QMutexLocker guard(&m_lock);
CURLcode res;
CURL* pCurl = curl_easy_init();
if(nullptr == pCurl)
{
return CURLE_FAILED_INIT;
}
if(m_bDebug)
{
curl_easy_setopt(pCurl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(pCurl, CURLOPT_DEBUGFUNCTION, OnDebug);
}
curl_easy_setopt(pCurl, CURLOPT_URL, strUrl.c_str());
curl_easy_setopt(pCurl, CURLOPT_POST, 1);
curl_easy_setopt(pCurl, CURLOPT_POSTFIELDS, strPost.c_str());
curl_easy_setopt(pCurl, CURLOPT_READFUNCTION, NULL);
curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, onWriteFunc);
curl_easy_setopt(pCurl, CURLOPT_WRITEDATA, static_cast<void*>(&strResponse));
curl_easy_setopt(pCurl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(pCurl, CURLOPT_CONNECTTIMEOUT, 8);
curl_easy_setopt(pCurl, CURLOPT_TIMEOUT, 8);
struct curl_slist *pSlist = nullptr;
pSlist = curl_slist_append(pSlist, sHeader.c_str());
curl_easy_setopt(pCurl, CURLOPT_HTTPHEADER, pSlist);
res = curl_easy_perform(pCurl);
curl_easy_cleanup(pCurl);
return res;
}
void CurlSdk::SetDebug(bool bDebug)
{
m_bDebug = bDebug;
}
3.2 生成的库:
4. sdk库调用demo
4.1 在pro文件中增加库链接和头文件包含:
4.2 拷贝库和头文件到demo工程上
4.3 demo代码 (客户端使用libcurl)
curlsdkdemo.h
#ifndef CURLSDKDEMO_H
#define CURLSDKDEMO_H
#include <QMainWindow>
#include "libcurlsdk.h"
namespace Ui {
class CurlSdkDemo;
}
class CurlSdkDemo : public QMainWindow
{
Q_OBJECT
public:
explicit CurlSdkDemo(QWidget *parent = nullptr);
~CurlSdkDemo();
private slots:
void on_Btn_SetBrightness_clicked();
void on_Btn_GetBrightness_clicked();
void on_Btn_SendUrlByGet_clicked();
void on_btn_post_set_clicked();
void on_btn_post_get_clicked();
void on_Btn_PostSendCustom_clicked();
void on_Btn_SetLogLevel_clicked();
void on_Btn_SetLogSave_clicked();
void slot_getHttpJobReturn(SDK_USER_INFO_T stUser, int eCmd, void* IpcParam, bool bSucc);
void on_Btn_SetAllImageConfig_clicked();
void on_Btn_GetAllImageConfig_clicked();
private:
Ui::CurlSdkDemo *ui;
};
#endif // CURLSDKDEMO_H
curlsdkdemo.cpp
#include "curlsdkdemo.h"
#include "ui_curlsdkdemo.h"
#include <QDebug>
#include <QCoreApplication>
#include <QtConcurrent>
#include "QFuture"
#include "QFutureWatcher"
#include <QMessageBox>
CurlSdkDemo::CurlSdkDemo(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::CurlSdkDemo)
{
//注册传递类型
qRegisterMetaType<SDK_USER_INFO_T>("SDK_USER_INFO_T");
connect(&LibCurlSdkHttp::getInstance(), SIGNAL(sig_HttpJobReturn(SDK_USER_INFO_T,int,void*,bool)),
this, SLOT(slot_getHttpJobReturn(SDK_USER_INFO_T,int,void*,bool)));
ui->setupUi(this);
}
CurlSdkDemo::~CurlSdkDemo()
{
delete ui;
}
/**********************************
* Log Operate
* ********************************/
void CurlSdkDemo::on_Btn_SetLogLevel_clicked()
{
LibCurlSdkHttp::getInstance().setLogLevel(LOG_LEVEL_INFO);
}
void CurlSdkDemo::on_Btn_SetLogSave_clicked()
{
QString sPath = qApp->applicationDirPath() + "/Log";
QDir dir(sPath);
if(!dir.exists())
{
dir.mkdir(sPath);//只创建一级子目录,即必须保证上级目录存在
}
LibCurlSdkHttp::getInstance().setLogSave(true, sPath);
}
/**********************************
* Http:
* Brightness (Get)
* ********************************/
void CurlSdkDemo::on_Btn_SetBrightness_clicked()
{
SDK_USER_INFO_T sUser;
snprintf(sUser.sIP, sizeof(sUser.sIP), "%s", "127.0.0.1");
sUser.nPort = 8080;
snprintf(sUser.sUserName, sizeof(sUser.sUserName), "%s", "admin");
snprintf(sUser.sPassword, sizeof(sUser.sPassword), "%s", "admin");
int nBrightness = ui->lineEdit_SetValByGet->text().toInt();
LibCurlSdkHttp::getInstance().SdkAddJob(sUser, API_TYPE_SET_BRIGHTNESS, (void*)(&nBrightness));
}
int g_nBrightness = 0;
void CurlSdkDemo::on_Btn_GetBrightness_clicked()
{
SDK_USER_INFO_T sUser;
snprintf(sUser.sIP, sizeof(sUser.sIP), "%s", "127.0.0.1");
sUser.nPort = 8080;
//snprintf(sUser.sUserName, sizeof(sUser.sUserName), "%s", "admin");
//snprintf(sUser.sPassword, sizeof(sUser.sPassword), "%s", "admin");
LibCurlSdkHttp::getInstance().SdkAddJob(sUser, API_TYPE_GET_BRIGHTNESS, (void*)(&g_nBrightness));
}
/**********************************
* Http:
* All Image Config (Get)
* ********************************/
IMAGE_SETTINGS_T g_stImageSet;
void CurlSdkDemo::on_Btn_SetAllImageConfig_clicked()
{
SDK_USER_INFO_T sUser;
snprintf(sUser.sIP, sizeof(sUser.sIP), "%s", "127.0.0.1");
sUser.nPort = 8080;
//snprintf(sUser.sUserName, sizeof(sUser.sUserName), "%s", "admin");
//snprintf(sUser.sPassword, sizeof(sUser.sPassword), "%s", "admin");
IMAGE_SETTINGS_T imageSet;
imageSet.nBrightness = ui->lineEdit_Brightness->text().toInt();
imageSet.nContrast = ui->lineEdit_Contrast->text().toInt();
imageSet.nSaturation = ui->lineEdit_Saturation->text().toInt();
imageSet.nSharpness = ui->lineEdit_Sharpness->text().toInt();
imageSet.nFLevel = ui->lineEdit_FLevel->text().toInt();
LibCurlSdkHttp::getInstance().SdkAddJob(sUser, API_TYPE_SET_IMAGEPARAMS, (void*)(&imageSet));
}
void CurlSdkDemo::on_Btn_GetAllImageConfig_clicked()
{
SDK_USER_INFO_T sUser;
snprintf(sUser.sIP, sizeof(sUser.sIP), "%s", "127.0.0.1");
sUser.nPort = 8080;
//snprintf(sUser.sUserName, sizeof(sUser.sUserName), "%s", "admin");
//snprintf(sUser.sPassword, sizeof(sUser.sPassword), "%s", "admin");
LibCurlSdkHttp::getInstance().SdkAddJob(sUser, API_TYPE_GET_IMAGEPARAMS, (void*)(&g_stImageSet));
}
/**********************************
* Http:
* Send Url (Get) no in thread
* ********************************/
void CurlSdkDemo::on_Btn_SendUrlByGet_clicked()
{
QString sUrl = ui->lineEdit_SetParamByGetUrl->text();
QString sResponse;
if(LibCurlSdkHttp::getInstance().SendHttpGet(sUrl, sResponse) == 0)
ui->textEdit_RecvGet->setText(sResponse);
}
/**********************************
* Http:
* Send Url (Get) no in thread
* ********************************/
int g_nTestParam = 0;
void CurlSdkDemo::on_btn_post_set_clicked()
{
int nValue = ui->lineEdit_SetValByPost->text().toInt();
SDK_USER_INFO_T sUser;
snprintf(sUser.sIP, sizeof(sUser.sIP), "%s", "127.0.0.1");
sUser.nPort = 8080;
//snprintf(sUser.sUserName, sizeof(sUser.sUserName), "%s", "admin");
//snprintf(sUser.sPassword, sizeof(sUser.sPassword), "%s", "admin");
LibCurlSdkHttp::getInstance().SdkAddJob(sUser, API_TYPE_SET_TESTPARAM, (void*)(&nValue));
}
void CurlSdkDemo::on_btn_post_get_clicked()
{
SDK_USER_INFO_T sUser;
snprintf(sUser.sIP, sizeof(sUser.sIP), "%s", "127.0.0.1");
sUser.nPort = 8080;
//snprintf(sUser.sUserName, sizeof(sUser.sUserName), "%s", "admin");
//snprintf(sUser.sPassword, sizeof(sUser.sPassword), "%s", "admin");
LibCurlSdkHttp::getInstance().SdkAddJob(sUser, API_TYPE_GET_TESTPARAM, (void*)(&g_nTestParam));
}
void CurlSdkDemo::on_Btn_PostSendCustom_clicked()
{
QString sUrl = ui->textEdit_PostUrl->toPlainText();
QString sParam = ui->textEdit_PostParam->toPlainText();
QString sHead = ui->textEdit_PostHead->toPlainText();
QString sResponse;
if(LibCurlSdkHttp::getInstance().SendHttpPost(sUrl, sParam, sHead, sResponse) == 0)
ui->textEdit_RecvPost->setText(sResponse);
}
/**********************************
* Http:
* Return Content
* ********************************/
void CurlSdkDemo::slot_getHttpJobReturn(SDK_USER_INFO_T stUser, int eCmd, void *IpcParam, bool bSucc)
{
qDebug() << __FUNCTION__ << "sIP:" << stUser.sIP << ", nPort:" << stUser.nPort << ", sUserName:" << stUser.sUserName <<\
"sPwd:" << stUser.sPassword;
Q_UNUSED(IpcParam);
QString sResult;
if(bSucc)
sResult = "Success!";
else
sResult = "Failed!";
switch(eCmd)
{
case API_TYPE_SET_BRIGHTNESS:
QMessageBox::information(this, "Title", sResult);
break;
case API_TYPE_GET_BRIGHTNESS:
ui->lineEdit_ShowBrightness->setText(QString::number(g_nBrightness));
break;
case API_TYPE_SET_IMAGEPARAMS:
QMessageBox::information(this, "Title", sResult);
break;
case API_TYPE_GET_IMAGEPARAMS:
qDebug() << __FUNCTION__ << " Brightness:" << g_stImageSet.nBrightness<<\
" Contrast:" << g_stImageSet.nContrast << " Saturation:" << g_stImageSet.nSaturation<<\
" nSharpness:" << g_stImageSet.nSharpness << " FLevel:" << g_stImageSet.nFLevel;
ui->lineEdit_GetBrightness->setText(QString::number(g_stImageSet.nBrightness));
ui->lineEdit_GetSharpness->setText(QString::number(g_stImageSet.nSharpness));
ui->lineEdit_GetContrast->setText(QString::number(g_stImageSet.nContrast));
ui->lineEdit_GetSaturation->setText(QString::number(g_stImageSet.nSaturation));
ui->lineEdit_GetFLevel->setText(QString::number(g_stImageSet.nFLevel));
break;
case API_TYPE_SET_TESTPARAM:
QMessageBox::information(this, "Title", sResult);
break;
case API_TYPE_GET_TESTPARAM:
ui->lineEdit_GetValByPost->setText(QString::number(g_nTestParam));
break;
}
}
4.4 demo 程序界面
5. http服务器 (服务器使用QTcpServer)
5.1 核心代码
5.1 myhttpserver.h
#ifndef MYHTTPSERVER_H
#define MYHTTPSERVER_H
#include <QMainWindow>
namespace Ui {
class myHttpServer;
}
QT_BEGIN_NAMESPACE
class QTcpServer;
class QTcpSocket;
QT_END_NAMESPACE
class myHttpServer : public QMainWindow
{
Q_OBJECT
public:
explicit myHttpServer(QWidget *parent = 0);
~myHttpServer();
int SumNums(QVector<int> nums);
protected slots:
void newConnectionSlot();
void errorStringSlot();
void sendMsg();
private:
QTcpServer *m_tcpServer;
QTcpSocket *m_tcpSocket;
QString m_SocketInfo;
int m_nBrightness;
int m_nContrast;
int m_nSaturation;
int m_nSharpness;
int m_nFLevel;
int m_nTestVal;
private:
Ui::myHttpServer *ui;
};
#endif // MYHTTPSERVER_H
5.2 myhttpserver.cpp
#include "myhttpserver.h"
#include "ui_myhttpserver.h"
#include <QTcpServer>
#include <QDebug>
#include <QTcpSocket>
#include <QJsonObject>
#include <QJsonDocument>
#include "QAbstractSocket"
#include "QStringList"
myHttpServer::myHttpServer(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::myHttpServer)
{
ui->setupUi(this);
m_tcpServer = new QTcpServer(this);
m_tcpServer->listen(QHostAddress::Any, 8080);
connect(m_tcpServer, SIGNAL(newConnection()), this, SLOT(newConnectionSlot()));
connect(m_tcpServer, SIGNAL(acceptError(QAbstractSocket::SocketError)), this, SLOT(errorStringSlot()));
}
myHttpServer::~myHttpServer()
{
m_tcpServer->close();
delete ui;
}
int myHttpServer::SumNums(QVector<int> nums)
{
int res = 0;
foreach(int num, nums) {
res += num;
};
return res;
}
void myHttpServer::newConnectionSlot()
{
ui->textEdit->append("newConnectionSlot() called!");
m_tcpSocket = m_tcpServer->nextPendingConnection();
connect(m_tcpSocket, SIGNAL(readyRead()), this, SLOT(sendMsg()));
}
void myHttpServer::errorStringSlot()
{
ui->textEdit->append(m_tcpServer->errorString());
}
void myHttpServer::sendMsg()
{
QByteArray data = m_tcpSocket->readAll();
QString m_requestInfo = data;
m_SocketInfo += m_requestInfo;
if (m_requestInfo.indexOf("=")>0)
{
ui->textEdit->append(m_SocketInfo);
//qDebug() << m_requestInfo;
QStringList list = m_SocketInfo.split(QRegExp("[\r\n]"), QString::SkipEmptyParts);
qDebug() << list;
if (!list.empty())
{
QStringList headlist = QString(list[0]).split(QRegExp("[ ]"));
QString m_requestMethod = headlist[0];
qDebug() << "headlist[1]:" << headlist[1];
if (m_requestMethod == "GET" && headlist[1].contains("my.rq"))
{
QStringList ParamList = headlist[1].split('&');
QVector<int> nums;
QString contentStr = "";
foreach(QString str, ParamList) {
if(str.contains("setbrightnessval"))
{
m_nBrightness = str.split('=')[1].toInt();
qDebug() << "m_nBrightness:" << m_nBrightness;
contentStr = "OK ";
}
else if(str.contains("setcontrastval"))
{
m_nContrast = str.split('=')[1].toInt();
contentStr = "OK ";
}
else if(str.contains("setsaturationval"))
{
m_nSaturation = str.split('=')[1].toInt();
contentStr = "OK ";
}
else if(str.contains("setsharpnessval"))
{
m_nSharpness = str.split('=')[1].toInt();
contentStr = "OK ";
}
else if(str.contains("setnflevelval"))
{
m_nFLevel = str.split('=')[1].toInt();
contentStr = "OK ";
}
else if(str.contains("getparam=brightnessval"))
{
contentStr += QString("OK brightnessval=%1").arg(m_nBrightness);
}
else if(str.contains("getparam=contrastval"))
{
contentStr += QString("OK contrastval=%1").arg(m_nContrast);
}
else if(str.contains("getparam=saturationval"))
{
contentStr += QString("OK saturationval=%1").arg(m_nSaturation);
}
else if(str.contains("getparam=sharpnessval"))
{
contentStr += QString("OK sharpnessval=%1").arg(m_nSharpness);
}
else if(str.contains("getparam=nflevelval"))
{
contentStr += QString("OK nflevelval=%1").arg(m_nFLevel);
}
};
//send msg
QString str = "HTTP/1.1 200 OK\r\n";
str.append("Server:nginx\r\n");
str.append("Content-Type:text/html;charset=UTF-8\r\n");
str.append("Connection:keep-alive\r\n");
str.append(QString("Content-Length:%1\r\n\r\n").arg(contentStr.size()));
if(!contentStr.isEmpty())
str.append(contentStr);
else
{
str.append(contentStr);
}
m_tcpSocket->write(str.toStdString().c_str());
}
if (m_requestMethod == "POST")
{
QString params;
if (QString(list[5]).size()>1)
{
params = list[5];
}
qDebug() << "params:" << params;
if (params.contains("setparam"))
{
QStringList valueList = params.split('=');
m_nTestVal = valueList[1].toInt();
QJsonObject res;
res.insert("param", QJsonValue(m_nTestVal));
QJsonDocument documentJson(res);
QString strJson(documentJson.toJson(QJsonDocument::Compact));
QByteArray dataArray = documentJson.toJson();
//send msg
QString str = "HTTP/1.1 200 OK\r\n";
str.append("Server:nginx\r\n");
str.append("Content-Type:application/json;charset=UTF-8\r\n");
str.append("Connection:keep-alive\r\n");
str.append(QString("Content-Length:%1\r\n\r\n").arg(strJson.size()));
str.append(strJson);
m_tcpSocket->write(str.toStdString().c_str());
}
else if(params.contains("getparam"))
{
QJsonObject res;
res.insert("param", QJsonValue(m_nTestVal));
QJsonDocument documentJson(res);
QString strJson(documentJson.toJson(QJsonDocument::Compact));
QByteArray dataArray = documentJson.toJson();
//send msg
QString str = "HTTP/1.1 200 OK\r\n";
str.append("Server:nginx\r\n");
str.append("Content-Type:application/json;charset=UTF-8\r\n");
str.append("Connection:keep-alive\r\n");
str.append(QString("Content-Length:%1\r\n\r\n").arg(strJson.size()));
str.append(strJson);
m_tcpSocket->write(str.toStdString().c_str());
}
}
}
m_SocketInfo = "";
}
}
5.2 服务器界面
6. 完整工程代码链接
https://download.csdn.net/download/linyibin_123/86952628