通讯编程上位机软件实现(SOCKET)——第一回
早就注册了博客园,却只在最近才开始关注,呵呵,错过了好多学习的机会。
第一次在园子里写博客,如写的有不恰当、不合理、错误之处,敬请拍砖~。
前一段时间做了一个Socket底层通讯的项目,采用TCP协议,上位机作为客户端,下位机作为服务器端。在做的过程中遇到了好多问题,诸如异步发送、接收、多线程、超时重传等等。在此把该项目拿出来,将项目的各个过程,涉及到得知识,通讯中常用的数据处理方式(封装成了DLL),竭尽自己所能,写出来与大家一同分享,如有不好之处,敬请指正。
一、TCP协议
相信做通讯的对TCP、UDP都不陌生。二者主要的区别有TCP是面向连接的、UDP面向无连接的;TCP是可靠的数据传输,有三次握手来保证数据的可靠性,UDP是不可靠的传输;TCP传输速度相对于UDP要慢。
具体涉及到TCP封包等等,我是菜鸟级的,懂的不多,留给大虾、大牛来讲吧,当然网上也有好多这方面的知识啦~。
选择TCP协议的原因,是我们的仪器检测的都是高危险的东西,所以要保证传输命令的正确性、可靠性。
二、协议格式
请求数据命令格式(上位机发送)
标识号(1字节)+数据包长度(1字节)+命令字(1字节)+命令序号(1字节)+具体命令(可以为0字节,具体内容,由上下位机来定)+校验码(1字节)
说明:
- 标识(1字节),只是对硬件的一个标识,一般用0xFN标识,其中N介于1到F之间,当然标识可以进行扩展,如果说仪器比较多,那标识从0xEN开始也无妨。
- 命令包长度(1字节),是从标识到最后验证码的所有数据的字节长度。
- 命令字(1字节),指示当前通讯的命令,例如,0XC1标识设置参数命令。
- 命令序号(1字节),是该数据包的一个时序上面的标识。十进制范围是1-255,当超过255时,对256求余,如果余数为0,则设置命令序号为1,从1开始递增。
- 具体命令就不说了,也就是数据包的核心东西吧,下位机需要的状态等等信息都包括在这里面。到后面,我会举例子。
- 校验码(1字节),这里校验码是这样制定的:整条命令中,除校验码本身外的所有字节相异或。原本是打算使用整条命令中,除校验码本省外所有字节相加取结果的最后1个字节,不管溢出与否。但是相加没有异或快,而且考虑到相加容易溢出,就摒弃了这种获取校验码的一种方式。
发送数据命令格式(下位机发送)
标识号(1字节)+数据包长度(1字节)+命令字(1字节)+命令序号(1字节)+仪器状态(1字节)+具体命令(可以为0字节,具体内容,由上下位机来定)+校验码(1字节)
说明:仪器状态(1字节)指示当前仪器是否正常工作,有没有故障信息等等。命令字和命令序号是从接收到得上位机命令中直接拷贝过来的,不用改变,其它的参照 请求数据命令 的说明。
上面是纯粹的协议,是在网络传输封装之前的协议,在数据包进行传输的过程中,传输层以及网络层都会对它添加信息,这是网络传输的事。
三、上位机超时与重发
上位机发送命令给下位机,下位机收到命令后返回相应信息,1秒钟上位机收不到响应信息或者收到得不是期望的响应信息(格式错误或者命令字错误或者命令序号错误或者数据包长度不完整等等),则认为本息通讯过程失败。
通讯失败后,上位机重发命令(命令字和命令序号不变),如果连续三次通讯过程失败,则认为通讯出错,终止通讯并弹出提示性信息。
四、下位机超时与重发
在测量过程中,如果下位机3秒钟之内收不到上位机发送的任何命令,则通讯出错,关闭仪器电源。
五、心跳包检测
鉴于上位机有时需要等待用户的某些操作才能发命令给下位机,类似这种情况,在协议中加入心跳包。其作用是为了防止正常通讯过程中,由于上位机的一些命令传输延迟(比如等待接收用户输入),下位机误以为超时,以至于中断了通讯过程。
心跳包采用定时1秒钟发送一次。只在正常通讯时,上位机需要做某些操作或等待用户的操作等,以至于通讯处于空闲状态,此时,上位机发送给下位机命令。