上篇给大家分析了如何在客户端进行服务器查询,今天再分析下在客户端的读和写的操作。下面这个函数囊括各路类型的读写操作,如异步或同步等等,实用性很强。

HRESULT synReadOrWrite(serverGroup* serverGroup, bool read, bool async) {char *buffer = (char *)malloc(MAXBYTE);OPCITEMRESULT *pResults = NULL;OPCHANDLE *hServerItem = NULL;HRESULT hResult = S_OK;IOPCSyncIO *pIOPCSyncIO = NULL;IOPCAsyncIO2 *pIOPCAsyncIO2 = NULL;if (async) {if (serverGroup->groupInfo->ipCPC == NULL) {hResult = buildCallback(serverGroup);if (FAILED(hResult)) {_tprintf(_T("Failed in buildCallback.\n"));return hResult;}}hResult = serverGroup->groupInfo->ipMgt->QueryInterface(IID_IOPCAsyncIO2, (void**)&pIOPCAsyncIO2);showConsole = false;}elsehResult = serverGroup->groupInfo->ipMgt->QueryInterface(IID_IOPCSyncIO, (void**)&pIOPCSyncIO);HRESULT *pErrors = NULL;if (FAILED(hResult)){_tprintf(_T("getting interface IID_IOPCSyncIO or IID_IOPCAsyncIO2 failed.\r\n"));goto end;}if (read) {_tprintf(_T("Enter tag names seperated by comma and press enter: "));fgets(buffer, MAXBYTE, stdin);size_t ln = strlen(buffer) - 1;if (buffer[ln] == '\n')buffer[ln] = '\0';char **result = NULL;size_t dwCount = 0;OPCITEMSTATE *pValues = NULL;if (strlen(buffer) == 0) {_tprintf(_T("tag names should be in format like this - tagName1, tagName2, tagName3\n"));hResult = E_INVALIDARG;goto end;}tokenizeString(buffer, ',', (char***)&result, &dwCount);pResults = (OPCITEMRESULT*)CoTaskMemAlloc(dwCount * sizeof(OPCITEMRESULT));hServerItem = (OPCHANDLE *)CoTaskMemAlloc(dwCount * sizeof(OPCHANDLE));pErrors = (HRESULT *)CoTaskMemAlloc(dwCount * sizeof(HRESULT));hResult = addItems(serverGroup->groupInfo->ipMgt, result, &pResults, &pErrors, dwCount);for (DWORD ii = 0; ii < dwCount; ii++) {if (!pErrors[ii])hServerItem[ii] = pResults[ii].hServer;}if (async) {DWORD dwCancelID;hResult = pIOPCAsyncIO2->Read(dwCount, hServerItem, *hServerItem, &dwCancelID, &pErrors); /* *hServerItem as transactionID*/}elsehResult = pIOPCSyncIO->Read(OPC_DS_DEVICE, dwCount, hServerItem, &pValues, &pErrors);if (FAILED(hResult) || hResult == S_FALSE){_com_error err(hResult);LPCTSTR errMsg = err.ErrorMessage();_tprintf(_T("Read failed: %s\r\n"), errMsg);for (DWORD ii = 0; ii < dwCount; ii++) {if (pErrors && pErrors[ii]) {if (pErrors[ii] == OPC_E_INVALIDHANDLE) {_tprintf(_T("element with index [%d] is invalid\n"), ii);}else{_com_error err(pErrors[ii]);errMsg = err.ErrorMessage();_tprintf(_T("Reading element with index [%d] failed: %s\n"), ii, errMsg);}}else{if (!async) {VARIANT vValue;VariantInit(&vValue);if (SUCCEEDED(VariantChangeType(&vValue, &pValues[ii].vDataValue, NULL, VT_BSTR))) {clientNode* tmpNode = findNode(true, hServerItem[ii]);_tprintf(_T("syncoReadWrite Read: %S %S\r\n"), tmpNode->clientName, vValue.bstrVal);}VariantClear(&vValue);}}}}else if (!async){for (DWORD ii = 0; ii < dwCount; ii++){VARIANT vValue;VariantInit(&vValue);if (SUCCEEDED(VariantChangeType(&vValue, &pValues[ii].vDataValue, NULL, VT_BSTR))) {clientNode* tmpNode = findNode(true, hServerItem[ii]);_tprintf(_T("syncoReadWrite Read: %S %S\r\n"), tmpNode->clientName, vValue.bstrVal);}VariantClear(&vValue);}}for (size_t i = 0; i < dwCount; i++) {if (!async)freeNode(hServerItem[i]);free(*(result + i));}free(result);if (!async)hResult = serverGroup->groupInfo->ipMgt->RemoveItems(dwCount, hServerItem, &pErrors);CoTaskMemFree(pValues);}else{_tprintf(_T("Enter tag name and value seperated by comma, and delimit them in semicolon: "));fgets(buffer, MAXBYTE, stdin);size_t ln = strlen(buffer) - 1;if (buffer[ln] == '\n')buffer[ln] = '\0';char **result = NULL, **nameValuePair = NULL, **names = NULL, **values = NULL;size_t dwCount = 0;if (strlen(buffer) == 0) {_tprintf(_T("tag name/value pair should be in format like this - tagName1, tagValue1; tagName2, tagValue2; tagName3, tagValue3\n"));hResult = E_INVALIDARG;goto end;}tokenizeString(buffer, ';', (char***)&result, &dwCount);names = (char**)malloc(sizeof(void*)*dwCount);values = (char**)malloc(sizeof(void*)*dwCount);for (DWORD ii = 0; ii < dwCount; ii++) {names[ii] = NULL;values[ii] = NULL;}size_t count = 0;for (DWORD ii = 0; ii < dwCount; ii++) {tokenizeString(result[ii], ',', (char***)&nameValuePair, &count);if (count == 2) {names[ii] = nameValuePair[0];values[ii] = nameValuePair[1];}else{_tprintf(_T("tag name and value should be paired. Check your input.\n"));for (size_t i = 0; i < dwCount; i++) {free(names[i]);free(values[i]);free(result[i]);}free(nameValuePair);free(names);free(values);free(result);goto end;}count = 0;}pResults = (OPCITEMRESULT*)CoTaskMemAlloc(dwCount * sizeof(OPCITEMRESULT));hServerItem = (OPCHANDLE *)CoTaskMemAlloc(dwCount * sizeof(OPCHANDLE));pErrors = (HRESULT *)CoTaskMemAlloc(dwCount * sizeof(HRESULT));hResult = addItems(serverGroup->groupInfo->ipMgt, names, &pResults, &pErrors, dwCount);for (DWORD ii = 0; ii < dwCount; ii++) {if (!pErrors[ii])hServerItem[ii] = pResults[ii].hServer;}VARIANT *varValue = (VARIANT *)CoTaskMemAlloc(dwCount * sizeof(VARIANT));for (DWORD ii = 0; ii < dwCount; ii++){if (!pErrors[ii]){varValue[ii].vt = VT_R4;varValue[ii].fltVal = strtof(values[ii], NULL);}}if (async) {DWORD dwCancelID;hResult = pIOPCAsyncIO2->Write(dwCount, hServerItem, varValue, *hServerItem, &dwCancelID, &pErrors); /* *hServerItem as transactionID */}elsehResult = pIOPCSyncIO->Write(dwCount, hServerItem, varValue, &pErrors);if (FAILED(hResult) || hResult == S_FALSE){_com_error err(hResult);LPCTSTR errMsg = err.ErrorMessage();_tprintf(_T("Write failed: %s\r\n"), errMsg);for (DWORD ii = 0; ii < dwCount; ii++){if (pErrors && pErrors[ii]) {if (pErrors[ii] == OPC_E_INVALIDHANDLE)_tprintf(_T("element with index [%d] is invalid\n"), ii);else {_com_error err(pErrors[ii]);errMsg = err.ErrorMessage();_tprintf(_T("Writing element with index [%d] failed: %s\n"), ii, errMsg);}}}}else{_tprintf(_T("Writing is successful.\n"));}if (!async)hResult = serverGroup->groupInfo->ipMgt->RemoveItems(dwCount, hServerItem, &pErrors);CoTaskMemFree(varValue);for (size_t i = 0; i < dwCount; i++) {if (!async)freeNode(hServerItem[i]);free(names[i]);free(values[i]);free(*(result + i));}free(names);free(values);free(result);}end:free(buffer);CoTaskMemFree(pResults);CoTaskMemFree(hServerItem);CoTaskMemFree(pErrors);if (pIOPCSyncIO)pIOPCSyncIO->Release();if (pIOPCAsyncIO2)pIOPCAsyncIO2->Release();return hResult;
}

程序比较长,大致的结构是这样的。根据传入的是否异步的值,从获得的OPC服务端的实例中取得执行IID_IOPCAsyncIO2(异步)或者IID_IOPCSyncIO(同步)的实例位置,如果是异步还需先告诉OPC服务器你的回调函数是什么,在这里是buildCallback(), 具体程序见下。根据传入的读写值来处理。先进行读的处理,根据异同步分别处理;然后是写的处理,也分异同步进行。当中也有一些辅助函数,我就不一一例举了,有需要的和我联系我再在这里贴出来。客户端打算告一段落,下篇讲讲服务端的安全问题。

HRESULT buildCallback(serverGroup *serverGroup) {HRESULT hResult = S_OK;hResult = serverGroup->groupInfo->ipMgt->QueryInterface(IID_IConnectionPointContainer, (void**)&serverGroup->groupInfo->ipCPC);if (FAILED(hResult)){_tprintf(_T("QueryInterface for IConnectionPointContainer failed.\r\n"));return hResult;}IConnectionPoint* ipCP = NULL;hResult = serverGroup->groupInfo->ipCPC->FindConnectionPoint(IID_IOPCDataCallback, &ipCP);if (FAILED(hResult)){_tprintf(_T("FindConnectionPoint failed.\r\n"));return hResult;}// create the callback object.Callback* ipCallback = new Callback();DWORD dwAdvise;hResult = ipCP->Advise(ipCallback, &dwAdvise);if (FAILED(hResult)){_tprintf(_T("Advise failed.\r\n"));return hResult;}return hResult;
}

OPC客户端分析 —— 读和写相关推荐

  1. 这是我读过写得最好的【秒杀系统架构】分析与实战!

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 来源:http://rrd.me/ewVWv 1 秒杀业务分析 2 ...

  2. 这是我读过写得最好的【秒杀系统架构】分析与实战!(转载)

    这是我读过写得最好的[秒杀系统架构]分析与实战!(转载) 1 秒杀业务分析 1. 正常电子商务流程 2. 秒杀业务的特性 2 秒杀技术挑战 1. 对现有网站业务造成冲击 2. 高并发下的应用.数据库负 ...

  3. zookeeper集群,每个服务器上的数据是相同的,每一个服务器均可以对外提供读和写的服务,这点和redis是相同的,即对客户端来讲每个服务器都是平等的。...

    zookeeper集群,每个服务器上的数据是相同的,每一个服务器均可以对外提供读和写的服务,这点和redis是相同的,即对客户端来讲每个服务器都是平等的.

  4. 用Delphi开发OPC客户端工具的方法研究

    用Delphi开发OPC客户端工具的方法研究[1]<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:o ...

  5. 面试官问:在读多写少的情况下,如何优化 MySQL 的数据查询方案

    作者 | 面试官问     责编 | 张文 来源 | 面试官问(ID:interviewer_asked) 面试官问:假设你负责的某业务在双十一期间要搞运营活动,公司投入了大量的营销费用进行推广,此举 ...

  6. 【收藏】C#面试题整理笔试篇(最全1000+道带答案)300道填空 + 300道选择 + 300道判断 + 70道读程序写结果和看程序填空 + 100道简答题

    <程序员>曾陪伴了无数开发者成长.<新程序员>全新归来,推荐给大家! <新程序员> 一.填空: 1.操作符( && )被用来说明两个条件同为真的情况 ...

  7. OPC通讯开发简介——基于WTOPCSVR的OPC服务器端和基于WTCLIENT的OPC客户端开发

    OPC通讯开发简介--基于WTOPCSVR的OPC服务器端和基于WTCLIENT的OPC客户端开发 说明 一.OPC技术背景及介绍 二.OPC通讯的流程(OPC经典架构) 三.OPC标准官方文件部分变 ...

  8. ceph 代码分析 读_分布式存储 Ceph 的演进经验 SOSP 2019

    『看看论文』是一系列分析计算机和软件工程领域论文的文章,我们在这个系列的每一篇文章中都会阅读一篇来自 OSDI.SOSP 等顶会中的论文,这里不会事无巨细地介绍所有的细节,而是会筛选论文中的关键内容, ...

  9. opc客户端_组态王作为OPC服务器的使用介绍,欢迎读者阅读

    组态王在原有的OPC客户端的基础上添加了OPC服务器的功能,实现了组态王对OPC的服务器和客户端的统一.通过组态王OPC服务器功能,用户可以更方便的实现其他支持OPC客户的应用程序与组态王之间的数据通 ...

最新文章

  1. 混合云是企业IT的未来吗?
  2. 数据结构与算法详解目录
  3. SpringBootApplication注解
  4. 江西省2019计算机二级报名日期,2020年3月江西计算机等级报名时间、报名入口【2019年12月18日-27日】...
  5. Glide4.0源码全解析(一),GlideAPP和.with()方法背后的故事
  6. 流水线效率计算公式_线束加工的生产效率、爬坡计划与产能提升浅读
  7. 苹果4s怎么绕过id激活_急急急,iPhone4s,怎么绕过激活锁。
  8. 奥维地图电脑端手机端不能用了,有没有可替代的地图工具
  9. java 复制文本到剪贴板,使用Java将文本复制到剪贴板
  10. 软件工程实验报告1-可行性分析
  11. 活动报名 | 保护儿童,保护未来!智源发布《面向儿童的人工智能北京共识》
  12. 从广域网云化看SD-WAN
  13. windows10获取超级管理员权限
  14. N卡版本查询--Windows命令下:
  15. ArcGIS——dwg与shp转换原理
  16. Java使用IKAnalyzer实现多关键字查询
  17. 肖博老师高中数学必备知识点总结最全版
  18. OpenGLES学习(一)图片显示
  19. 怎么用计算机求逆矩阵,计算机是怎么求解线性方程的(矩阵乘和求逆)
  20. 云队友丨以末求财,用本守之

热门文章

  1. iPhoneX安全区域与H5引发的问题(Safe Area)
  2. 《大数据时代》观后感
  3. 中国电信计算机通信笔试题,中国电信入职考试题 求大神解答!
  4. svn获取代码时报错【 C:\Users\ADMINI~1\APPData\Loca\Temp\svn.... 找不到指定路径】
  5. 如何关闭手机提醒事项的推送
  6. 使用Transformer构建自己的机器翻译服务
  7. cv2.inRange()函数---提取票据中红色印章
  8. 概率论--随机事件及运算
  9. RocketMQ中的消息类型种类(二)
  10. 中国联通今年5G投资350亿元!附2019业绩PPT全文