自从搞清楚了Cache里面可以建立TCP连接之后,就有一种冲动,把单向连接的设备用一个程序搞定,于是做了一个FileClient。
具体的就是把本地的文件通过TCP连接发送到Cahce的后台,然后在Cache的studio里面再解析相关的文件,最后把结果保存到数据库。
这么做的好处是显而易见的:
1、解析放在了Cache里面,ObjectScript像是一个脚本语言,随时编辑随时编译,只是解析文本的话,效率贼高。
2、很多电脑其实很难安装Cache数据的控件,例如VISM.ocx控件,有些设备的电脑是定制的,控件根本没法注册。如果只是用TCP连接来传输数据,只要是windows的电脑都能跑起c#的程序来,最多就是.net框架不一样,但是我们可以通过编译生成不同.net版本的程序,基本上只要能拷贝过去就能直接运行。还有一个是vism.ocx控件是单线程的,处于阻塞模式时,程序退出进程还存在。
3、前端程序就一个,装上配置一下就搞定,省的改来改去还要去部署。
4、理论来说,如果只是socket编程,mac、linux也是可以搞定的。
于是乎,我就用c#写了一个程序,用【STX】【ETX】来封装要发送的内容,Cache收到数据后进行解析,然后保存到数据。
装到Cobas z480上,终于解决了vism.ocx控件用不了的问题,程序跑起来也很好。
但是,问题又来了,当我们用来传输一个酶标仪300k的文本文件的时候,麻烦了,数据会不全,会丢包!
也就是说我们不能一股脑把文件全推过去,得分包,得校验!
考虑到现有的ASTM框架已经用的很熟悉了,考虑用ASTM协议来传输数据!
于是乎,吭哧吭哧干起来,一个ASTM框架最多发送239个byte的数据,因此就把文本数据分割为N个239byte的数据包来发送:
1、客户端发送【ENQ】
2、Cache回复【ACK】
3、客户端先读取239byte数据,然后加上【STX】加上FrameNum,加上【ETB】和【EXT】,再加上校验CheckSum,最后加上【CR】【LF】,发送!
4、Cache校验数据后,回复【ACK】
5、客户端再读取239byte…
…
6、客户端发送【EOT】
7、Cache回复【ACK】
好了,文件传输完成!我找了个文本传输试一试,一试验,傻眼了,传得乱七八糟的!
咋回事?原来是中文的问题,中文的编码一般占2个byte,也就意味着其中的一个byte可能会和【STX】这些控制字符冲突!
那咋办?查了查UTF-8的编码心灰意冷,因为更变态,还是可变长度的!莫非我要去找个很生僻的汉子如“丿”来当控制符用!真的就搞不了么?
不对,记得UNICODE编码是固定长度的,任何字符都是两个byte编码,只要长度固定,我想应该有办法吧!
查了查unicode的编码表,看见了熟悉的面孔,【STX】等这些控制符依然还在呀!只是需要两个字节,16进制表示是 U+ 00 02 ,只要控制字符不和其它的数据冲突,那就好办,ASTM协议继续搞起来!
把Cache端的编码格式改成Unicode:
OPEN io:(:serverPort:/IOTABLE=”Unicode”):10
那么Cahce会自动读取两个byte组合成一个char了。
同样的客户端也要改,比如发送ENQ就要发送2个byte的数据:
byte[] byteENQ = new byte[2];
byteENQ[0] = (byte)ASTM.ENQ;
byteENQ[1] = 0;
同时239这个内容的长度也必须改,因为可能会把一个字符的两个byte分割到两个数据包中去,那么就又会乱码,所以改成偶数238,这样就确保一个数据包中字符的byte都是完整的!
好了,搞定,中文终于也可以完美的传输了!
等等,问题又来了,Cache报错了!报啥错误?MAXSTRING,原来Cache的数据字符串最大长度也就3w,如果要使用更长的需要修改服务器参数,这个我们还是不动了。
于是找来了能存更长的字符串的一个类:
s allRecord =##class(%GlobalCharacterStream).%New()
利用%GlobalCharacterStream的Write和Read方法来存储和读取这个300k的字符串!
好了,到这里总算是解决了全部问题了!
最后注意一点的是%GlobalCharacterStream的ReadLine方法只识别CRLF这种换行,如果只有一个CR是截断不了的,会一起全部都读出来!
这下遇到单向的仪器只要把程序拷贝过去,然后回来在Studio里面解析一下就可以了!半个小时搞定!
上图是分包传输的数据日志!
如无特别说明,本博客文章皆为原创。转载请说明,来自吵吵博客。
原文链接:http://chaochaoblog.com/archives/3857
吵吵微信朋友圈,请付款实名加入:
文章不错非常喜欢