HINTERNET 句柄

WinINet句柄详解

这篇文章的内容可以简单总结如下:

  1. WinINet函数创建和使用类型为HINTERNET的句柄
  2. HINTERNET句柄不能与其他类型的句柄互换使用
  3. InternetCloseHandle关闭HINTERNET句柄
  4. 有多种类型的HINTERNET句柄,它们形成一个树结构,如下图所示:

 

图中带阴影的方框创建的HINTERNET句柄被下一级的函数使用;背景空白的方框不创建HINTERNET句柄,仅使用上一级函数创建的句柄。HttpSendRequestHttpSendRequestExHttpEndRequest有些特殊,它们的下层函数不是使用它们创建的HINTERNET句柄,而是HttpOpenRequest创建的句柄,在调用这三个函数后,就可以调用下一级的函数了。

 

本节包含用于WinINet函数的句柄,以及它们的层次结构的信息。

关于HINTERNET句柄

WinINet函数创建和使用类型为HINTERNET的句柄。HINTERNET句柄不能与其他类型的句柄互换。因此,HINTERNET句柄不能用于ReadFile或者CloseHandle等函数。同样地,其他类型的句柄也不能用于WinINet函数。比如说,CreateFile返回的句柄不能传递给InternetReadFile

InternetCloseHandle函数用于关闭HINTERNET句柄。注意,句柄值很快被回收重用。因此,如果关闭一个句柄,然后立即生成一个新句柄,则新句柄的值很可能与刚被关闭句柄的值相同。

 

句柄层次结构

HINTERNET句柄形成了一个树结构。InternetOpen函数返回的句柄是树的根节点,InternetConnect函数返回的句柄则占有下一级,而FtpOpenFileFtpFindFirstFileHttpOpenRequestGopherOpenFileGopherFindFirstFile函数返回的句柄则是叶子节点。

下图展示了HINTERNET句柄的层次结构。图中每个方框代表返回HINTERNET句柄的一个函数。

Functions that create handles

最顶层的是InternetOpen函数,它创建根节点。下一层包括InternetOpenUrlInternetConnect函数。组成了最后一层的是使用InternetConnect返回的句柄的函数。

下图展示了依赖于由InternetOpenUrl创建的句柄的函数。带阴影的方框代表返回HINTERNET句柄的函数,而空白方框代表使用HINTERNET句柄的函数。

Functions that use the InternetOpenUrl handle

InternetQueryDataAvailableInternetReadFileInternetSetFilePointer函数使用InternetOpenUrl创建的HINTERNET句柄。

 

FTP层次结构

下图展示了依赖于InternetConnect返回的FTP会话句柄的FTP函数。带阴影的方框代表返回HINTERNET句柄的函数,空白方框表示使用它们所依赖的函数创建的HINTERNET句柄的函数。

Functions that use the FTP session handle

FtpCreateDirectoryFtpDeleteFileFtpGetCurrentDirectoryFtpGetFileFtpPutFileFtpRemoveDirectoryFtpRenameFileFtpSetCurrentDirectory函数都使用InternetConnect创建的HINTERNET句柄。

下图展示了返回句柄的两个FTP函数,以及依赖于它们的函数。带阴影的方框代表返回HINTERNET句柄的函数,空白方框表示使用它们所依赖的函数创建的HINTERNET句柄的函数。 

Functions that use the handle from FtpOpen and FtpFindFirstFile

InternetFindNextFile函数依赖于FtpFindFirstFile创建的句柄;而InternetReadFileInternetWriteFile使用FtpOpenFile创建的句柄。

 

Gopher层次结构

下图显示了用于Gopher协议的函数。带阴影的方框表示返回HINTERNET句柄的函数,空白方框表示使用它们所依赖的函数创建的HINTERNET句柄的函数。 

Gopher related functions

GopherGetAttribute函数依赖于InternetConnect创建的句柄。InternetFindNextFile使用GopherFindFirstFile创建的句柄。GopherOpenFile创建的句柄被InternetQueryDataAvailableInternetReadFile使用。

 

HTTP层次结构

下图显示了用于HTTP协议的函数。带阴影的方框表示返回HINTERNET句柄的函数,空白方框表示使用它们所依赖的函数创建的HINTERNET句柄的函数。  

Functions that use the handle from HttpOpenRequest

HttpAddRequestHeadersHttpQueryInfoHttpSendRequestHttpSendRequestExInternetErrorDlg函数依赖于HttpOpenRequest创建的句柄。

下图展示了使用由HttpOpenRequest创建、然后被HttpSendRequest发送的句柄的函数。带阴影的方框表示返回HINTERNET句柄的函数,空白方框表示使用它们所依赖的函数创建的HINTERNET句柄的函数。  

Functions that use the handle after HttpSendRequest

HttpOpenRequest返回的句柄被HttpSendRequest使用后,就可以被InternetQueryDataAvailableInternetReadFileInternetSetFilePointer使用了。 

Functions that use the handle after HttpSendRequestEx

HttpOpenRequest返回的句柄,在被HttpSendRequestEx使用后,就可以被HttpEndRequestInternetReadFileExInternetWriteFile使用了。调用HttpEndRequest之后,句柄可以被InternetReadFileInternetSetFilePointerInternetQueryDataAvailable使用。

void LCMESClass::Connect() { CriticalSectionLock lock(m_cs); // 使用类成员 CCriticalSection m_cs; if (m_GVariant.m_MesConfig->Enable == 0) { m_connectionState = ConnectionState::Disconnected; return; } std::string hostname = m_GVariant.m_MesConfig->Host; int port = m_GVariant.m_MesConfig->Port; // 已连接且目标相同则直接返回 if (m_pConnection && m_connectionState == ConnectionState::Connected) { if (m_cachedHost == m_GVariant.m_MesConfig->Host && m_cachedPort == m_GVariant.m_MesConfig->Port) { return; } } m_connectionState = ConnectionState::Connecting; // 释放旧连接(如果存在) if (m_pConnection) { delete m_pConnection; m_pConnection = nullptr; } // 设置全局超时参数 HINTERNET hSession = (HINTERNET)m_Session; // ✅ 正确获取 HINTERNET 句柄 if (hSession) { DWORD connectTimeout = 5000; // 5 秒 DWORD sendTimeout = m_GVariant.m_MesConfig->SendTimeout; DWORD recvTimeout = m_GVariant.m_MesConfig->RecvTimeout; InternetSetOption(hSession, INTERNET_OPTION_CONNECT_TIMEOUT, &connectTimeout, sizeof(connectTimeout)); InternetSetOption(hSession, INTERNET_OPTION_SEND_TIMEOUT, &sendTimeout, sizeof(sendTimeout)); InternetSetOption(hSession, INTERNET_OPTION_RECEIVE_TIMEOUT, &recvTimeout, sizeof(recvTimeout)); } try { // 创建新连接 m_pConnection = m_Session.GetHttpConnection( m_GFunction.String2CString(m_GVariant.m_MesConfig->Host), m_GVariant.m_MesConfig->Port, _T(""), // username _T("") // password ); if (m_pConnection) { m_connectionState = ConnectionState::Connected; // 更新缓存信息 m_cachedHost = m_GVariant.m_MesConfig->Host; m_cachedPort = m_GVariant.m_MesConfig->Port; CString logMsg; logMsg.Format(_T("MES连接成功: %s:%d"), m_GFunction.String2CString(m_cachedHost), m_cachedPort); addInfo(m_GFunction.CString2String(logMsg)); } else { m_connectionState = ConnectionState::Error; addErrInfo("MES连接失败: 无法创建HTTP连接"); } } catch (CInternetException* pEx) { TCHAR szError[1024]; pEx->GetErrorMessage(szError, 1024); m_connectionState = ConnectionState::Error; addErrInfo("MES连接异常: " + m_GFunction.CString2String(szError)); pEx->Delete(); } }是不是有问题,算便给host和port都能成功
最新发布
09-26
#include "pch.h" #include "MESInterface.h" #include "Loger.h" extern CGlobalVariant m_GVariant; // 全局变量 extern CGlobalFunction m_GFunction; // 全局函数 extern Loger m_Loger; // 全局Log类 extern CActionFlow m_GActionFlow; // 动作流程 extern CDlgDevError m_dlgError; MESInterface* MESInterface::m_pInstance = nullptr; MESInterface * MESInterface::GetInstance() { static CCriticalSection cs; CriticalSectionLock lock(cs); // 使用我们之前定义的 RAII 锁 if (m_pInstance == nullptr) // 错误:m_pInstance 未声明 { m_pInstance = new MESInterface(); } return m_pInstance; } void MESInterface::PostTask(TaskType type, const CString & param) { TaskItem* pItem = new TaskItem(); pItem->type = type; pItem->param = param; { //CriticalSectionLock lock(m_cs); // 使用自定义锁 m_taskList.AddTail(pItem); } m_taskEvent.SetEvent(); // 触发事件 } UINT MESInterface::WorkerThreadProc(LPVOID pParam) { MESInterface* pThis = (MESInterface*)pParam; while (!pThis->m_bStopThread) { DWORD dwWait = WaitForSingleObject(pThis->m_taskEvent.m_hObject, INFINITE); if (dwWait != WAIT_OBJECT_0) continue; if (pThis->m_bStopThread) break; TaskItem* pItem = nullptr; { CriticalSectionLock lock(pThis->m_cs); // 使用自定义锁 if (!pThis->m_taskList.IsEmpty()) { pItem = pThis->m_taskList.RemoveHead(); } } if (pItem) { pThis->ProcessTask(pItem); delete pItem; } } return 0; } void MESInterface::ProcessTask(TaskItem * pItem) { switch (pItem->type) { case TASK_CHECK: ExecuteCheck(m_GFunction.CString2String(pItem->param)); break; case TASK_EVENT_DEVICE_STATE_CHANGED: ExecuteDeviceStop(static_cast<StopCode>(_ttoi(pItem->param))); break; } } int MESInterface::ExecuteCheck(string sn) { CriticalSectionLock lock(m_cs); // 线程安全调用 MesJTInfo info; info.WP = QString::fromLocal8Bit(m_GVariant.m_MesConfigFile->WP.c_str()); info.JZ = QString::fromLocal8Bit(m_GVariant.m_MesConfigFile->JZ.c_str()); info.User = QString::fromLocal8Bit(m_GVariant.m_MesConfigFile->User.c_str()); info.Line = QString::fromLocal8Bit(m_GVariant.m_MesConfigFile->Line.c_str()); info.Machine = QString::fromLocal8Bit(m_GVariant.m_MesConfigFile->Machine.c_str()); info.OffLine = m_GVariant.m_MesConfigFile->OffLine; info.Tray = QString::fromLocal8Bit(m_GVariant.m_MesConfigFile->Tray.c_str()); info.Barcodes.append(QString::fromLocal8Bit(sn.c_str())); QString jsonString = info.toJsonString(); Response res = SendMesJTInfo(static_cast<string>(jsonString.toLocal8Bit())); if (res.Code == 0 || res.Result == "OK") { return 1; } else { addErrInfo(static_cast<string>(res.Msg.toLocal8Bit())); return -1; } return 0; } void MESInterface::ExecuteDeviceStop(StopCode state) { CriticalSectionLock lock(m_cs); // 线程安全调用 MesEquStop maState; string eventDesc = ""; int deviceStatus = 0; switch (state) { case Waiting: eventDesc = "待机"; deviceStatus = 1; break; case Wroking: eventDesc = "作业"; deviceStatus = 2; break; case Faulted: eventDesc = "故障"; deviceStatus = 3; break; case Stopped: eventDesc = "关机"; deviceStatus = 4; break; default: eventDesc = "开机"; deviceStatus = 0; break; } maState.StopCode = deviceStatus; maState.StopType = QString::fromLocal8Bit(eventDesc.c_str()); maState.Machine = QString::fromLocal8Bit(m_GVariant.m_MesConfigFile->Machine.c_str()); maState.StartTime = QDateTime::currentDateTime(); maState.JZ = QString::fromLocal8Bit(m_GVariant.m_MesConfigFile->JZ.c_str()); maState.Line = QString::fromLocal8Bit(m_GVariant.m_MesConfigFile->Line.c_str()); maState.User = QString::fromLocal8Bit(m_GVariant.m_MesConfigFile->User.c_str()); QString jsonString = maState.toJsonString(); Response res = SendMesEquStop(static_cast<string>(jsonString.toLocal8Bit())); if (res.Code == 0 || res.Result == "OK") { return; } else { addErrInfo(static_cast<string>(res.Msg.toLocal8Bit())); return; } } QString convertSimple(const QString& input) { if (input.length() != 17) return input; // 确保长度正确 QString year = input.mid(0, 4); QString month = input.mid(4, 2); QString day = input.mid(6, 2); QString time = input.mid(9, 8); // 提取时间部分 return QString("%1-%2-%3 %4").arg(year, month, day, time); } int MESInterface::updataMes(TestData testData) { MesMTF mesInfo; auto MTFvariantMap = testData.toVariantMap(); // 这里拿到了OrderedVariantMap的值 QString MTFString = "{"; for (const QString& key : MTFvariantMap.keys()) { QVariant variant = MTFvariantMap[key]; QString value = variant.toString(); MTFString.append("\"" + key + "\":\"" + value + "\","); } MTFString.chop(1); MTFString.append("}"); MTF Data; Data.Barcode = testData.Barcode; Data.ST = convertSimple(testData.Basic.Time); if ("PASS" == testData.Result.Aggregate.trimmed() || "BEST" == testData.Result.Aggregate.trimmed()) { Data.Result = "OK"; } else { Data.Result = "NG"; } Data.MTF = MTFString; auto DatavariantMap = Data.toVariantMap(); QString DataString = "[{"; for (const QString& key : DatavariantMap.keys()) { QVariant variant = DatavariantMap[key]; QString value = variant.toString(); if (key == "MTF") { DataString.append("\"" + key + "\":" + value + ","); } else { DataString.append("\"" + key + "\":\"" + value + "\","); } } DataString.chop(1); DataString.append("}]"); mesInfo.Num = 1; mesInfo.JZ = QString::fromLocal8Bit(m_GVariant.m_MesConfigFile->JZ.c_str()); mesInfo.User = QString::fromLocal8Bit(m_GVariant.m_MesConfigFile->User.c_str()); mesInfo.Line = QString::fromLocal8Bit(m_GVariant.m_MesConfigFile->Line.c_str()); mesInfo.Machine = QString::fromLocal8Bit(m_GVariant.m_MesConfigFile->Machine.c_str()); mesInfo.Tray = QString::fromLocal8Bit(m_GVariant.m_MesConfigFile->Tray.c_str()); mesInfo.OffLine = m_GVariant.m_iFrontRunMode == 0 ? 1 : 0; mesInfo.Data = DataString; QString jsonString = "{"; auto mesinfo = mesInfo.toVariantMap(); for (const QString& key : mesinfo.keys()) { QVariant variant = mesinfo[key]; QString value = variant.toString(); if (key == "Data") { jsonString.append("\"" + key + "\":" + value + ","); } else { jsonString.append("\"" + key + "\":\"" + value + "\","); } } jsonString.chop(1); jsonString.append("}"); Response res = SendMesEquStop(static_cast<string>(jsonString.toLocal8Bit())); if (res.Code == 0 || res.Result == "OK") { return 1; } else { addErrInfo(static_cast<string>(res.Msg.toLocal8Bit())); return -1; } return 0; } void MESInterface::PullMes() { CriticalSectionLock lock(m_cs); // ✅ 加锁 sSC_PullMes.Init(); updataRun = true; while (true) { int iRtn = FL_PullMes(); if (-1 == iRtn) { updataRun = false; break; } Sleep(5); } } int MESInterface::FL_PullMes() { int iRtn = 0; switch (sSC_PullMes.nStep) { case 0: addInfo(sSC_PullMes, 5, "开始巡检MES目录", true); return 0; case 5: iRtn = checkFolder(); if (-1 == iRtn) { addInfo(sSC_PullMes, ST_ERR, "巡检MES目录失败"); } if (1 == iRtn) { sSC_PullMes.nStep = 10; } else { sSC_PullMes.SetDelay(5, 1000); } return 0; case 10: if (m_File.checkFileExist(m_destinationFolder, m_currentFileNames)) { sSC_PullMes.nStep = 15; } else { addInfo(sSC_PullMes, ST_ERR, "检查MES文件是否存在失败"); } return 0; case 15: if (m_bufferFileNames.size() == 0) { sSC_PullMes.nStep = ST_END; } else { sSC_PullMes.nStep = 20; } return 0; case 20: if (m_iItemIndex <= m_bufferFileNames.size() - 1) { m_qstrRemoveFile = m_bufferFileNames[m_iItemIndex]; QString tempFile = m_destinationFolder + "\\" + m_qstrRemoveFile; if (deserializeFromJsonFile(tempFile, m_MesInfo)) { m_GVariant.configItemFile->copyToTestData(m_MesInfo); if (m_MesInfo.Barcode == "" || m_MesInfo.Barcode.length() < 5) { m_iItemIndex = 0;//将索引归零 addInfo(sSC_PullMes, 15, "条码长度小于5:条码为" + (string)m_MesInfo.Barcode.toLocal8Bit()); m_bufferFileNames.removeOne(m_bufferFileNames[m_iItemIndex]); } else { m_iItemIndex++; addInfo(sSC_PullMes, 25, "准备上传单角度数据"); } } else { addInfo(sSC_PullMes, ST_ERR, "文件" + (string)tempFile.toLocal8Bit() + "json序列化失败"); } } else { addInfo(sSC_PullMes, ST_END, "缓存文件已上传完毕"); } return 0; case 25: iRtn = updataMes(m_MesInfo); if (-1 == iRtn) { sSC_PullMes.nStep = ST_ERR; } if (1 == iRtn) { //清空列表中的 m_bufferFileNames.removeOne(m_qstrRemoveFile); m_iItemIndex = 0;//将索引归零 addInfo(sSC_PullMes, 15, "单角度上传完成,开始缓存新MES数据"); } return 0; case ST_DELAY: if (GetTickCount() - sSC_PullMes.dwStart >= sSC_PullMes.dwDelay) { sSC_PullMes.nStep = sSC_PullMes.nStepNext; } return 0; case ST_ERR: return -1; case ST_END: sSC_PullMes.ulCountEnd = m_GFunction.GetCPUPerformanceCounter(); sSC_PullMes.dCycleTime = (sSC_PullMes.ulCountEnd - sSC_PullMes.ulCountStart) / 1000000.0; sSC_PullMes.AddCTRecordEnd(m_GActionFlow.m_iRecordCycleTime, "sSC_PullMes over, CycleTime:", sSC_PullMes.dCycleTime); sSC_PullMes.Init(); return 1; } return 0; } void MESInterface::StartWorkerThread() { if (m_pWorkerThread == nullptr) { m_pWorkerThread = AfxBeginThread(WorkerThreadProc, this); } } void MESInterface::StopWorkerThread() { if (m_pWorkerThread != nullptr) { m_bStopThread = true; m_taskEvent.SetEvent(); // 唤醒线程退出 WaitForSingleObject(m_pWorkerThread->m_hThread, INFINITE); m_pWorkerThread = nullptr; } } MESInterface::MESInterface() { updataRun = false; StartWorkerThread(); } MESInterface::~MESInterface() { StopWorkerThread(); } // 请求镜头过线情况接口 /// http://10.93.2.17:8083/datasnap/rest/THttp1/MesJTInfo Response MESInterface::SendMesJTInfo(string info) { string host = m_GVariant.m_MesConfigFile->Host; int port = m_GVariant.m_MesConfigFile->Port; string path = m_GVariant.m_MesConfigFile->Check; string username = m_GVariant.m_MesConfigFile->UserName; string password = m_GVariant.m_MesConfigFile->PassWord; Response resp = Send(info, host, port, path, username, password); if (SUCCESS == resp.Code) { return ParseRcv(static_cast<string>(resp.Msg.toLocal8Bit())); } return resp; } // 工序接口- MTF检查 /// http://10.93.2.17:8083/datasnap/rest/THttp1/MesZZ Response MESInterface::SendMesMTF() { string host = m_GVariant.m_MesConfigFile->Host; int port = m_GVariant.m_MesConfigFile->Port; string path = m_GVariant.m_MesConfigFile->Save; string username = m_GVariant.m_MesConfigFile->UserName; string password = m_GVariant.m_MesConfigFile->PassWord; string info = ""; Response resp = Send(info, host, port, path, username, password); if (SUCCESS == resp.Code) { return ParseRcv(static_cast<string>(resp.Msg.toLocal8Bit())); } return resp; } // 其它接口-设备异常上报 /// http://10.93.2.17:8083/datasnap/rest/THttp1/MesEquStop Response MESInterface::SendMesEquStop(string info) { string host = m_GVariant.m_MesConfigFile->Host; int port = m_GVariant.m_MesConfigFile->Port; string path = m_GVariant.m_MesConfigFile->DeviceInfoCollerct; string username = m_GVariant.m_MesConfigFile->UserName; string password = m_GVariant.m_MesConfigFile->PassWord; Response resp = Send(info, host, port, path, username, password); if (SUCCESS == resp.Code) { return ParseRcv(static_cast<string>(resp.Msg.toLocal8Bit())); } return resp; } int MESInterface::addInfo(string & info) { if (m_logInfo == info) { return 1; } m_logInfo = info; m_Loger.RecordLogMes(m_logInfo); // 发送消息,传递快照指针 if (NULL != m_GActionFlow.m_hwdMainView) { // 使用PostMessage CString* pMsg = new CString(CA2CT(info.c_str())); ::SendMessage(m_GActionFlow.m_hwdMainView, WM_MESINFO, (WPARAM)pMsg, 0); } return 0; } int MESInterface::addInfo(StepCtrl & crtl, int next, string info, bool blag) { addInfo(info); crtl.nStep = next; if (blag) { crtl.ulCountStart = m_GFunction.GetCPUPerformanceCounter(); crtl.InitRecordString(); } if (next == ST_ERR) { addErrInfo(info); } return 0; } int MESInterface::addErrInfo(string info) { info = "MES" + info; m_GActionFlow.LightOpenRed(); m_dlgError.SetError(info); m_Loger.RecordLogError(info); //m_gMes.DeviceStateChanged(DeviceState::Faulted); 不能用,MES服务端出现问题后不能再调用,会导致死循环 AfxMessageBox(m_GFunction.String2CString(info), MB_OK | MB_ICONSTOP | MB_SYSTEMMODAL); m_GActionFlow.LightOpenYellow(); return 0; } void MESInterface::Connect() { CriticalSectionLock lock(m_cs); if (m_GVariant.m_MesConfigFile->Enable == 0) { m_connectionState = ConnectionState::Disconnected; return; } // 已连接且目标相同则直接返回 if (m_pConnection && m_connectionState == ConnectionState::Connected) { if (m_cachedHost == m_GVariant.m_MesConfigFile->Host && m_cachedPort == m_GVariant.m_MesConfigFile->Port) { return; } } m_connectionState = ConnectionState::Connecting; // 释放旧连接(如果存在) if (m_pConnection) { delete m_pConnection; m_pConnection = nullptr; } // 设置全局超时参数 HINTERNET hSession = (HINTERNET)m_Session; // ✅ 正确获取 HINTERNET 句柄 if (hSession) { DWORD connectTimeout = 5000; // 5 秒 DWORD sendTimeout = m_GVariant.m_MesConfigFile->SendTimeout; DWORD recvTimeout = m_GVariant.m_MesConfigFile->RecvTimeout; InternetSetOption(hSession, INTERNET_OPTION_CONNECT_TIMEOUT, &connectTimeout, sizeof(connectTimeout)); InternetSetOption(hSession, INTERNET_OPTION_SEND_TIMEOUT, &sendTimeout, sizeof(sendTimeout)); InternetSetOption(hSession, INTERNET_OPTION_RECEIVE_TIMEOUT, &recvTimeout, sizeof(recvTimeout)); } try { // 创建新连接 m_pConnection = m_Session.GetHttpConnection( m_GFunction.String2CString(m_GVariant.m_MesConfigFile->Host), m_GVariant.m_MesConfigFile->Port, _T(""), // username _T("") // password ); if (m_pConnection) { m_connectionState = ConnectionState::Connected; // 更新缓存信息 m_cachedHost = m_GVariant.m_MesConfigFile->Host; m_cachedPort = m_GVariant.m_MesConfigFile->Port; CString logMsg; logMsg.Format(_T("MES连接成功: %s:%d"), m_GFunction.String2CString(m_cachedHost), m_cachedPort); addInfo(m_GFunction.CString2String(logMsg)); } else { m_connectionState = ConnectionState::Error; addErrInfo("MES连接失败: 无法创建HTTP连接"); } } catch (CInternetException* pEx) { TCHAR szError[1024]; pEx->GetErrorMessage(szError, 1024); m_connectionState = ConnectionState::Error; addErrInfo("MES连接异常: " + m_GFunction.CString2String(szError)); pEx->Delete(); } } Response MESInterface::Send(const string & info, const string & hostname, const int & port, const string & apiPath, string m_username, string m_password) { CriticalSectionLock lock(m_cs); // 检查连接状态 if (m_connectionState != ConnectionState::Connected) { Connect(); // 尝试重连 // 重连后仍然失败 if (m_connectionState != ConnectionState::Connected) { Response resp; resp.Code = NETWORK_ERROR; resp.Msg = "MES connection not established"; return resp; } } Response resp; if (!m_pConnection) { resp.Code = NETWORK_ERROR; resp.Msg = "Not connected to server. Call Connect() first."; return resp; } try { auto deleter = [](CHttpFile* p) { if (p) delete p; }; std::unique_ptr<CHttpFile, decltype(deleter)> pFile( m_pConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST, m_GFunction.String2CString(apiPath)), deleter); // 设置请求头 CString strHeaders = _T("Content-Type: application/json\r\n"); strHeaders += _T("Authorization: Basic ") + EncodeBasicAuth(m_GFunction.String2CString(m_username), m_GFunction.String2CString(m_password)) + _T("\r\n"); // 转换请求数据 CString strData = m_GFunction.String2CString(info); pFile->SendRequest ( strHeaders, (DWORD)strHeaders.GetLength(), (LPVOID)(LPCTSTR)strData, (DWORD)strData.GetLength() ); DWORD dwStatusCode; pFile->QueryInfoStatusCode(dwStatusCode); CString strResponse; if (dwStatusCode == HTTP_STATUS_OK) { TCHAR szBuffer[1024]; while (pFile->Read(szBuffer, 1023) > 0) { strResponse += szBuffer; } } if (dwStatusCode != HTTP_STATUS_OK) { resp.Code = HTTP_ERROR; resp.Msg = QString::number(dwStatusCode); return resp; } resp.Msg = QString::fromLocal8Bit(m_GFunction.CString2String(strResponse).c_str()); pFile->Close(); } catch (CInternetException* pEx) { TCHAR szError[1024]; pEx->GetErrorMessage(szError, 1024); resp.Msg = QString::fromLocal8Bit(m_GFunction.CString2String(szError).c_str());// 异常信息写入resultMSG pEx->Delete(); resp.Code = NETWORK_ERROR; return resp; } resp.Code = SUCCESS; return resp; } // 添加连接状态查询方法(公共接口) ConnectionState MESInterface::GetConnectionState() const { return m_connectionState; } Response MESInterface::ParseRcv(string & msg) { QJsonDocument jsonDoc = QJsonDocument::fromJson(QByteArray::fromStdString(msg)); QJsonObject j = jsonDoc.object(); return Response::fromJson(j); } CString MESInterface::EncodeBasicAuth(const CString& username, const CString& password) { // 拼接用户名:密码 CString credentials = username + _T(":") + password; // 使用 Qt 转换宽字符 CString 到 QByteArray(UTF-8) QString qCredentials = QString::fromWCharArray(credentials.GetString()); QByteArray utf8Credentials = qCredentials.toUtf8(); // Base64 编码 QByteArray base64Data = utf8Credentials.toBase64(); // 将 Base64 数据转为 CString 返回 return CString(base64Data.constData()); } int MESInterface::checkFolder() { CriticalSectionLock lock(m_cs); // ✅ 加锁 m_currentFileNames.clear(); QString m_sourceFolder = QString::fromLocal8Bit(m_GVariant.m_MesConfigFile->Path_SourceTestFile.c_str()) + "\\MES" + QDateTime::currentDateTime().addDays(-1).toString("yyyyMMdd"); m_destinationFolder = QString::fromLocal8Bit(m_GVariant.m_MesConfigFile->Path_DestTestFile.c_str()) + "\\" + QDateTime::currentDateTime().addDays(-1).toString("yyyyMMdd"); bool result1 = m_File.moveAllFiles(m_sourceFolder, m_destinationFolder, m_currentFileNames); m_sourceFolder = QString::fromLocal8Bit(m_GVariant.m_MesConfigFile->Path_SourceTestFile.c_str()) + "\\MES" + QDateTime::currentDateTime().toString("yyyyMMdd"); m_destinationFolder = QString::fromLocal8Bit(m_GVariant.m_MesConfigFile->Path_DestTestFile.c_str()) + "\\" + QDateTime::currentDateTime().toString("yyyyMMdd"); bool result2 = m_File.moveAllFiles(m_sourceFolder, m_destinationFolder, m_currentFileNames); if (result1 || result2) { if (m_currentFileNames.size() > 0) { for (auto item : m_currentFileNames) { m_bufferFileNames.append(item); } return 1; } } else { return -1; } return 0; } 外部多线程调用这个类用来上传MES数据,过线检查和上传设备状态等事件,是否有啥问题
09-26
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值