现在我需要通过PC发送指令对下位机进行运动控制,下位机是staubli CS8C机器人控制器。相当于PC,有自己的程序语言,通过socket建立tcp连接通讯。
     控制就是和下位机通过socket“聊天”,例如让它走就发走的相应字符串。下位机接收到命令字符串,解析然后执行相应动作。平时常用的命令也不多,如:相对位置运动、绝对位置运动、停、上下电、匀速运动、得到当前坐标等,现在做法是根据用户输入操作用socket发送相应命令字符串,接下来PC端需要得到刚才发送的这条命令的反馈信息(下位机收到命令后向上位机发送下位机是否执行了上位机的命令)。现在是在每次发送完命令接着接收下位机发送的字符串,如
     send(socket,strCmd,strlen(strCmd));
     recv(socket,strRev,nLen);
socket为阻塞模式的,使用没问题,现在每当发完运动命令后会调用waitstop()函数,此函数接管主消息循环直到得到下位机返回运动停止消息才从函数退出。
我的实现是又开了个线程,来每隔xxx毫秒询问一次设备运动停止没,也使用和上面的一样的一发一收,直到收到停止回应结束。    主程序线程会开定时器询问下位机设备当前坐标,也是一发一收。
这种写法就有问题了,常常一线程卡住,怀疑卡在recv函数上,多线程使用一个socket,我加了关键区把这一发一收抱起来。
         EnterCriticalSection(&CriticalSection);
::send(g_socket,szCommand,strlen(szCommand),0);
nRecv=recv(g_socket,szResponse,64,0);
LeaveCriticalSection(&CriticalSection);
这样仍然不能避免其中一线程卡死,好像这个时候另一线程也会卡死,搞不懂,是这种写法不好还是?
换用异步模式socket加关键区好像还行,
现在想问一下好的模式该怎样写?其实之前用过gailil运动控制卡API,上述问题人家实现的比较好,例如发送一命令代码如下
re=m_Controller.Command(szCommand,szResponse, sizeof(szResponse));
根据re返回值就能得知运动控制卡执行情况,就是看不到源码?不知道是曾样实现的?
现在一种想法是用CAsyncSocket,当用户有操作就发送相应命令,然后等待事件受信,在重载的OnReceive中收到下位机的响应消息后setEvent();这样用户一个操作函数返回。或者把经常要询问的下位机状态做个表,如当前坐标,运动与否。定时根据下位机刷新上位机的这份表的副本,以后询问状态信息则不再询问下位机而直接从这张表返回。
再就是建个命令队列,每当要发送指令就放入队列里,然后使用一个出口统一逐一发送。使用一个入口统一收到的也逐一放入队列,软后逐一取出来解析。大家有做过类似的说说经验,谈谈健壮的程序该怎样写,猜猜gailil运动控制卡API的实现