卡斯柯的ATS系统,协议接口都有,应该不是秘密。
要做一个服务器,接收ATS信息,转发,不过做接收DEMO的时候遇到点小问题。
贴一下原协议:
第一张图是5秒一次的行车信息。
第二张图是不定时的进出正线信息(也就是上线,开始运营,或者下线,休整)
位置比较固定,作用比较关键的是header,length,message_flag和CRC。
第一个是协议头,第二个是“长度”(不是真长度,是他后边的数据域的长度,不包括CRC,总之比较绕的计算方式),第三个是类型,这不是两种协议包吗?判断用的,最后那个就是校验了。
第三张图是收到信息对ATS的反馈
因为ATS每五秒发送一次所有列车的行车信息,有列车变轨(进出正线)时发送一次进出正线信息,列车数量大概120辆。
ATS协议行车信息包大小:8bytes+15*nbytes,不知道他们对0列车是怎么定义的,总之,1列车是23,2列车是38,以此类推。。。
ATS协议进出正线信息包大小:17bytes
看起来是很平淡的信息量,不过还是脑洞大开,考虑一些极端情况:假设,在极微小的read()间隙,刚好在行车信息之间出现了进出正线信息。又或者进出正线信息在行车信息之前出现。总之就是缓冲区堆积上了,这样read()就是多条协议包。然后这样就做个游标,读出数据后遍历一下,这个遍历是根据协议内部的长度信息进行相应的移动来完成的,需要对ATS协议有一定了解(读来读去多读几遍呗),总之不是特别难。
因为协议有CRC校验,而之前他写的什么ISO3309之类的我不懂,就搁置了,处理逻辑做完了就做CRC校验,一做,脑洞更大了。之前的DEMO假设数据都正确了,现在加上CRC校验,就考虑数据不正确怎么办?如果数据不正确,那么用以判断协议长度的变量也就不正确,也就不知道协议的边缘在哪。不知道协议的边缘在哪,意味着一次read出现一个CRC校验错误后,后边的信息都废了。
遂去找人讨论,一讨论,问题更恶心了,“数据太多,一次读不出来你怎么办?你接到的不一定就是头部!”
这个确实没法解,通过协议头吗?协议头内容为0xa0a0,但是协议头就一定对吗?校验了吗?而且包内数据里就不能恰好有0xa0a0吗?所以也不能就拿0xa0a0来确认协议头在哪吧?
另外,反馈确认信息只有一个头部0xb0b0,这缓冲区堆积情况明显就不在考虑范围之内,有两条数据都区分不开到底是对哪条信息的确认,别说多的数不清的数据包了。区分开了又有什么用,按目前的理解,ATS只管自顾自的发信息,没什么互动。
最后,说CRC也不是确保无错的,CRC都错了怎么办?
目前只能顺其自然,最起码我加了头部判定和协议类型判定,还有CRC,一切错误数据都是纸老虎——被弃置,看人家5秒发一次行车信息,甚至还说“没有进出站等关键信息收到行车信息DDS也不进行转发”,所以是容许一定的时间误差的。另外加大read()频率(本来就很快)和加大用来read()的buffer应该都是有效途径。
但是问题终究是要解决的,别人的压力大的服务器又都是如何处理的,也许别的协议更健壮?而这个ATS协议不行?
还有系统机制问题——缓冲区到底有多大,存多少数据?我接收buffer可以设置和它一样大从而一次接收完成吗?
最新悖论
因为不定长,CRC位置必须依靠length变量推测,而不先校验CRC,又怎能确定length值无误?
所以,舍弃错误数据才是王道,或利用读取速度优势靠时间消磨,或直接调用系统调用(暂时我也不知道具体是哪个调用,fflush()之类?待查!)