【开发工具套装】
VS2019 VS2017 SQLServer2012
VS打包安装文件InstallerProjects
【调试助手套装】
虚拟串口vspdp9.0
串口调试助手UartAssist V4.3.13
网络调试助手NetAssist V4.3.15
【Modbus学习套装】
Modbus调试工具软件套装
需求说明:
下位机是plc,西门子1200
下位机只能做服务器端,监听一个端口,不能主动给客户端发送消息(原计划是上位机也是监听一个端口,供下位机来访问,上传数据,结果现实很骨感)
上位机(pc)充当客户端,可以主动连接下位机交换信息
具体需求:
1,上位机给下位机下达工作数据
(比如下位机是生产纸张,上位机需要发给下位机纸张的尺寸,数量等数据)
2,下位机会在某个特定的时间“发送”数据,供上位机“接收”
(注意 “发送” 是加上引号的,因为服务器(下位机)是不能主动给客户端(上位机,pc)发送数据的,这是此文需要解决的问题)
需求1毫无难度,直接在用户在上位机点击下单,上位机即可创建一个socket将相关数据下传即可
重点来看看需求2;
可以想象为服务器与客户端(浏览器)
不妨以秒杀为例,
客户端(浏览器)提交秒杀请求(相当于这里的上位机给下位机下单),由于秒杀并发很大,不能实时返回数据(一般是异步下单,这里不深究)
客户端如果需要知道秒杀的结果,会在浏览器(客户端)通过轮询查询订单状态(如果有,则表示下单成功)
在需求2中,“客户端” 就指的是上位机创建的“socket”,socket是唯一和下位机沟通的途径,而且下位机不能创建socket,主动发数据给上位机,那么上位机创建得到socket,能否让他成为一个永久的客户端,上位机定时的取这个socket里的数据呢??
答案是肯定的:
思路:
将socket封装成一个单例,需求1和需求2中的客户端(上位机的socket) 使用同一个socket
问题又来了:
问题1:
如果上位机正在给下位机下传工作信息,下位机恰好也在此时完成了一些工作,将工作状态通过socket(由上位机创建的)发送数据,那么会有可能出现冲突,有点乱套
解决:
尝试加锁,让这个socket同一时间只能用在 过程1 ( 上位机给下位机下传工作数据) 或者 过程2(上位机周期读取socket中的数据(也就是下位机返回的工作完成情况这些数据)),
通过加锁:让这一个socket在某一个时刻,只能用于过程1或者过程2
问题2:
如果socket挂掉了?该如何获取与下位机的交互数据的“要道” 呢??
解决:
封装后的socket单例类,在使用socket读、写时,加上try catch 捕捉 SocketException,出现此异常,socket连接就是断开了,重新是用封装好的单例类的getInstance方法获取 socket对象,重建连接
此单例实现代码如下:
其中需要注意的是:
1,Semphore这一锁(信号量),参数指定此锁允许最多同时被多少个线程使用某一个资源(或者是资源的个数)
2,isDead 标记,用来标记当前单例对象是否断开(socket),如果是断开的,在getInstance是对其做了判断
如果没有单例对象,或者单例对象标记为“死亡”,那么就创建新的单例对象
第2点保证了,同一时刻,只能有一个线程使用socket
第2点保证了,socket的持久通信,及时下位机重启或者其他原因导致socket连接中断,也能重新创建连接
使用:
以下位机状态“返回“”为例”
1 先获取锁(获取资源)
2 业务操作
3 再释放锁(释放资源)
定时任务改进说明:
最初是在定时器里面没有使用单例,每个周期到了,将new Socket(),发现随着执行的任务次数增加,会出现问题
内存资源的问题:
比如我创建2000个socket:
创建之前:
创建之后:变化感觉不大,但是idea电脑卡死将近5秒
定时任务是会一直执行的,如果是4000次又会是怎样的呢?
当创建完1563个的时候已经抛异常了,有一瞬间cpu使用率100%
改下代码,创建socket使用完就将其close,测试结果竟然让调试助手还是无响应了。
上面的测试过程是为了说明创建socket是需要耗费资源,那么就得减少socket的创建,完成任务就好。
限时特惠:本站每日持续更新5-20节内部创业项目课程,一年会员
只需199元,全站资源免费下载点击查看详情
站长微信:
jjs406