一个具有协议转换功能的应用(二) TCP服务器类的实现 第二部分:以太网服务器设计 TCPServer类直接使用了例程中的代码,这里就不再列出来了。这里重点说明一下TCPCustom类的修改。 修改TCPCustom类增加CAN总线操作方面的代码,在进行代码修改前,先将通讯数据格式进行一下定义。 前导同步码 | 有效数据长度 | 命令码 | 数据 | 0xEB 0x90 0xEB 0x90 0xEB 0x90 | 0x00 0x00 | 0x01 命令 0x02 数据 | 若干 |
源码分析如下: 1) 客户端通讯接收数据线程 采用原TCPCustom的内容基本不用做特别修改,尽在线程退出的地方,判断如果已经打开CAN总线,线程退出后应该关闭CAN总线接口。 /*-------------------------------------------------------------------- 【函数介绍】: 此线程用于监听与客户端连接的socket通讯的事件,例如当接收到数据、 连接断开和通讯过程发生错误等事件 【入口参数】: lparam:无类型指针,可以通过此参数,向线程中传入需要用到的资源。 在这里我们将CTCPCustom类实例指针传进来 【出口参数】: (无) 【返回 值】: 无 ---------------------------------------------------------------------*/ void* CTCPCustom::SocketDataThread(void* lparam) { CTCPCustom *pSocket; char TxBuf[2000]; int TxLen; //得到CTCPCustom类实例指针 pSocket = (CTCPCustom*)lparam; //定义读事件集合 fd_set fdRead; int ret; struct timeval aTime; aTime.tv_sec = 1; aTime.tv_usec = 0; while( 1 ) { //收到退出事件,结束线程 if( pSocket->m_ExitThreadFlag ) { break; } //置空读事件集合 FD_ZERO(&fdRead); //给pSocket设置读事件 FD_SET(pSocket->m_socketfd, &fdRead ); //调用select函数,判断是否有读事件发生 aTime.tv_sec = 1; aTime.tv_usec = 0; ret = select(0, &fdRead, NULL, NULL, &aTime); if( ret<0 ) { //关闭socket close( pSocket->m_socketfd ); break; } else { //判断是否读事件 if(FD_ISSET(pSocket->m_socketfd,&fdRead)) { pSocket->RecvLen = recv(pSocket->m_socketfd, pSocket->RecvBuf, 1024,0); if (pSocket->RecvLen < 0 ) { //与客户端端连接的Socket错误 printf( "Socket errorn"); //关闭socket close(pSocket->m_socketfd); break; } //表示连接已经从容关闭 else if( pSocket->RecvLen == 0) { printf( "Close socket %dn", pSocket->m_socketfd ); //关闭socket close(pSocket->m_socketfd); break; } else { //对接收的数据进行处理,这里为简单处理数据回发 pSocket->RecvBuf[pSocket->RecvLen]=0; printf( "RCV:%sn", pSocket->RecvBuf); TxLen = pSocket->DataPro( TxBuf ); if( TxLen>0 ) { pSocket->SendData( TxBuf, TxLen ); } //处理完毕 } } } } |