项目需求:对PLC上存储的数据进行读取,并转存到数据库
语言:C++、DDL
所需知识点:Socket通信、Modbus帧结构、C++中数据库的操作、多线程、Linux
项目进度拆解记录(不会做就是困难!!管它简不简单!)
1、Socket通信。
由于之前一直采用串口通信,并未了解过其他通信机制,所以&*%¥%!@#(啥也不会)。打开网页、视频各种学习,发现是自己掌握的TCP通信机制,但自己只是理论掌握,不具备代码实现的能力,在CSDN、GitHub寻找各种资源后,终于写出了自己的Socket.cpp。这只是开始,耗时一周(严重浪费!!!)
1.1、Socket通信连接问题
在不打开服务器的情况下,程序会一直停在连接时(我用的是connect连接)。且打开服务器后,通信连接成功,但会报出一个错误(自己写的,取出connect返回值为-1)。这里理想的优化方案是连接服务器超时时,报出一个错误,然后再尝试继续连接。实现方式学习中……
2、Modbus帧结构。(这个我可以,最喜欢帧结构!)
2.1、Socket通信连接问题
耗时一个下午,各处查找资料后,学习到Modbus帧中的位所代表的信息。——这里安利两个小工具(Modbus Slave和Modbus Poll)下载地址(链接:https://pan.baidu.com/s/1YNz1wbb6PeRrVDhg2mrdgQ 提取码:z2a0 --来自百度网盘超级会员V4的分享)——下图可以即为帧结构,显然~~~所以~~~这里懂了。在代码实现的过程中,由于不可抗力的被要求加入CRC校验算法,然后打开GitHub一顿扒拉,读了很多之后,自己写了一段适合自己的,然后!发现CRC在TCP里不需要(内心:hhhh我就当学习了吧,rm -rf /* One week later!)
2.2、忽略MODBUS通信机制造成的错误
在modbus中,下发信息后,目标机会回复一条信息(即便是在下发修改指令)。此处,由于我在下发修改指令后,并未进行接收数据的操作,导致我其它读值部分读取的全是修改的返回数据。于是便在修改后加入一个recv接收socket中的缓冲区进行清空缓冲区(十分重要),用数组接受完后,记得释放数组,不然也会引发异常。
3、MySQL。
之前只用过Access和SQLServers,众所周知,这俩都是图形化操作界面,真的是很友好了,首先,拿到外包提供的数据库不会链接到自己的库中,只好转txt然后Ctrl CV(神技)自己执行。这里感谢好朋友的帮助,提供给我Navicat,用起来感觉MySQL也就洒洒水啦,有了图形化操作界面我乱点都点的出来,嘿嘿嘿。。。。回归正题,之后用C++链接数据库,这里应该不算是一个难点了,无非是增删改查,各种资源一看就懂。
3.1 数据库写入时的中文乱码。
本来在写连接的时候,有些函数设置了语句:
const char* query = "set names \'GBK\'";
mysql_query(_mysql, query);
但是由于并未在我写入之前进行设置,所以我把这里的设置改到对数据库的连接中,连接上数据库后立刻设置,Nice!
3.2 重复写入机制的优化
由于对对某一个表需要重复写入200条记录,每次的值都相当于是刷新替代旧的值。为了防止对数据库写入超行和写入数据重复,我在写入前优先使用查询语句进行查询内容是否存在,存在则选择UPDATE更新值,不存在的话使用INSERT插入值。
--------------------------------------------------------------分割------------------------------------------------------------
然后突然发现有一个REPLACE语句,可以直接更换,相当于对我的查询和插入做了一个集合。对接口来说,在整个写入过程中,时间减少了一半,且REPLACE写入机制刚好符合我的要求,果断选择更换到REPLACE语句实现。
--------------------------------------------------------------分割------------------------------------------------------------
抱着重温Mysql知识的想法,去官网看了一下插入语言。突然发现对INSERT插入时,有一个关键字IGNORE可以忽视主键存在,进行重复插入。于是取消REPLACE方法。(此处有一个猜想,在调用REPLACE时,前、后端对数据库的异步操作,会不会对前端来说,在某次查询数据时,由于REPLACE引起的清空而导致表中数据为NULL然后报错?)有待验证~
4、关于整个接口的实现方式引发的不同版本。
姑且称多线程为V1.0,单线程为V2.0。问题来了,在V1.0版本中需要多线程的知识(我真的超级喜欢多线程,顺带学习了C++的多线程实现,声明实现~)问题来了,在多线程中我肯定不能用同一个socket连接和数据库连接吧,于是大方地给了每个线程发了一个新的。这里就得加上互斥锁了!但,问题来了,数据库新建连接多了导致我写入超时(这里是因为我在每个线程后未断开数据库)。由于时间的影响,本来找到的解决办法:数据库的线程池操作,就被我pass掉了。于是Copy出副本,改V2.0,用同一个socket和数据库连接(但愿不会崩)一切就挺顺利,剩下的代码大同小异的查询PLC然后转存到数据库,祭出神技:Ctrl C(V)!! (One week later)等待有空了一定把那个多线程的给搞出来,多线程在逻辑上更符合多功能实现!
5、C++。
按理说这个应该是首要问题,但是对其的学习贯穿了我整个开发过程,属于边学习边实现。不过对const char *、char *、char、string还是区别不清(有问题即时百度,虽然有点浪费时间)。
5.1、Printf假死
C++中的printf竟然还会出现假死状态,我这里真的弄不懂为什么在连接socket和数据库的时候,我的printf不输出值,而且假死在数据库的连接中!!!为什么我的缓冲区就满了呀!我就写了几个字符而已啊!!!看了网上的
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)