⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 carditfa.cpp

📁 一个vxworks开发的snmp的程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/****************************************************
* History *
2002.12.05 改正CBuffer类里面的Free空间计算错误
2002.12.02 修改ThreadProc,改正了其中每次接收可能包含部分帧的处理中的潜在逻辑漏洞
2002.10.31 增加E1测试接口CtlE1Test()
****************************************************/
/*
1、CtlGetAbn()还没有确定上传的内容
2、没有提交用户名和密码
*/
// CardItfa.cpp : Defines the initialization routines for the DLL.
//
#include "stdafx.h"
#include "CardItfa.h"
#include "CBuffer.h"

#include <conio.h>
#include <winioctl.h>
#include <math.h>

#include "winsock2.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


//-----------------------------------------------------------
//#define ETHDATASIZE		1200

#define DATAHEAD			14
#define DATABODY			1200
#define BUFDATASIZE			(DATAHEAD+DATABODY)
#define BUFRECVDATANUM		160
//#define BUFSENDDATANUM	4

#define BUFCMDSIZE			70
#define BUFRECVSYNCMDNUM	8
#define BUFRECVASYCMDNUM	32
//#define BUFSENDCMDNUM		4

#define MAXRETRYTIMES		2
//-----------------------------------------------------------
//全局变量定义
CBuffer * pBufDataRecv = 0, *pBufDataSend = 0,
	*pBufSynCmdRecv = 0, *pBufAsyCmdRecv = 0, *pBufCmdSend = 0;//各种缓冲区
char ThreadCtlCode; //0:强制停止,-1:已经停止;1:允许开始
char bBeRun = 0;
WSAEVENT hEvent[2] = {0,0};//hEvent[0]用于通知可接收,hEvent[1]用于中止接收阻塞
SOCKET sClient = 0;	/* socket fd's */
STRUCT_ERROR strError;
unsigned char FrameID = 0, SendID;
//UINT hTimer = 0;
HANDLE hMutexSend = NULL; //控制发送的次序,使得FrameID的更新安全


//-----------------------------------------------------------

BEGIN_MESSAGE_MAP(CCardItfaApp, CWinApp)
	//{{AFX_MSG_MAP(CCardItfaApp)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CCardItfaApp construction

CCardItfaApp::CCardItfaApp()
{
	// TODO: add construction code here,
	// Place all significant initialization in InitInstance
}

/////////////////////////////////////////////////////////////////////////////
// The one and only CCardItfaApp object

CCardItfaApp theApp;



UINT ThreadProc(LPVOID pParam)
{
	/*****************************************
	* Frame始终指向待处理数据的头
	* nRvLen2始终表示待处理数据的长度
	*****************************************/
//	ThreadCtlCode = 1;
//	BOOL bNewFrame = 1;//1 表示本包是是新的一帧的开始,0 表示本包为接上一包为一帧的一部分
	BOOL Rtn = 1;
	int nDiscardNum = 0, CurrentIDRx = -1;
	unsigned char *Frame, ch[2][BUFDATASIZE];//*Recv;//*InComp;	
	int nRvLen = 0, nRvLen2 = 0;
	UINT nFrameLen = 0;//, nInCompGot = 0;
	//BOOL bInComp = FALSE;
	unsigned char EchoData[5];
	//bool bEchoTest;

	bBeRun = 1;
	//Recv = ch[1];
	Frame = ch[1];
	/***************************************************
	* 在循环中最重要的两个参数的变化为 Frame 和 nRvLen2
	* Frame 标识未处理数据的头指针
	* nRvLen2 标识未处理数据的长度
	****************************************************/
	while(ThreadCtlCode > 0)			
	{		
//		if((WSAWaitForMultipleEvents(2,hEvent,FALSE,WSA_INFINITE,FALSE) - WSA_WAIT_EVENT_0) == 0)
		{//如果是由于套接字有事件触发
//			Recv = ch[1];//恢复接收缓冲区地址
			nRvLen = recv(sClient,(char *)ch[1],BUFDATASIZE,0);//新收到的数据都保存在ch[1]开始的内存区域			
			if(nRvLen < 0)
			{
//				int x = WSAGetLastError();
				Sleep(10);
				continue;
			}
			if(nRvLen == 0)
			{//正常关闭
				Rtn = 0;
				break;
			}
			nRvLen2 += nRvLen;//nRvLen2表示当前要处理的全部长度
			//WSAResetEvent(hEvent[0]);
			if(nRvLen > 1214)
				int dd = 0;

			while(nRvLen2 > 0)	//程序跳出点1			//当前还未处理完
			{
				if(nRvLen2 >= 4)						//当前未处理帧能够解出帧长度
				{
					nFrameLen = Frame[2];
					nFrameLen <<= 8;
					nFrameLen += Frame[3] + 4;
					if(nFrameLen > BUFDATASIZE)			//如果帧长度非法,即失步
					{
						//清除全部当前数据
						nRvLen2 = 0;
//						Frame = ch[1];
						break;	//循环跳出点2
					}			
				}else//一帧的长度至少为4,当剩下超短,无法得到帧长度信息时
				{
					nFrameLen = 4;//这样统一由底下的操作一起搬移				
				}
				if(nFrameLen > (UINT)nRvLen2)
				{
					int i;
					for(i = 0; i < nRvLen2; i ++)	//将残帧拷贝至ch[0]区域
						*(ch[1] - nRvLen2 + i) = Frame[i];//因为重叠内存区域的拷贝会引起冲突
					//memcpy(ch[1]-nInCompGot,Frame,nInCompGot);//将本次接收数据最后部分填充到最前面
//					Frame = ch[1] - nRvLen2;//Frame始终指向未处理数据的头
					break;			//循环跳出点3
				}else
				{
					nRvLen2 -= nFrameLen;		//1、更新nRvLen2的值
				}	
				if(Frame[1] == CurrentIDRx)//如果和前次收到的帧ID相同,则认为是单方向重发产生的重复信息,丢弃
				{
					Frame += nFrameLen;			//2、1更新一次处理内Frame的值
					continue;
				}
				else
					CurrentIDRx = Frame[1];
				if(Frame[0] == 0x05)//Data
				{
					if(nDiscardNum > 0)
					{
						nDiscardNum --;
						Frame += nFrameLen;		//2、2更新一次处理内Frame的值
						continue;
					}
					//在一帧数据分为若干包发来时,先要预判断是否有足够的空间
					//出现溢出时,是一帧统计一次,而不是一包统计一次
					if((Frame[12] & 0x20) == 0) // splite to severl packet 
					{
						nDiscardNum = Frame[12] & 0x1F;
						nDiscardNum = (nDiscardNum << 8) + Frame[13];
						if((pBufDataRecv->PutTo(Frame,nFrameLen,nDiscardNum)) == 0)
						{						
							strError.DataRecvOver ++;						
						}
						else
						{
							nDiscardNum = 0;
						}						 
					}
					else//分割数据报的最后一包,或者完整一包,或者是截断数据报
					{
						if((pBufDataRecv->PutTo(Frame,nFrameLen)) == 0)
							strError.DataRecvOver ++;
					}
					
				}else if(Frame[0] == 0x04)//上行指令
				{
					if(Frame[4] == 0x90)//Echo_Request
					{
						memcpy(EchoData,Frame,5);
						//bEchoTest = true;
						EchoData[0] = 0x03;
						EchoData[4] = 0x91;
						//if(sClient)
							send(sClient,(char *)EchoData,5,0);
					}else
					if(Frame[4] == 0x80)//AsyCmd
					{
						if((pBufAsyCmdRecv->PutTo(Frame,nFrameLen)) == 0)					
							strError.AsyCmdRecvOver ++;
					}else				//SynCmd
					{
						if((pBufSynCmdRecv->PutTo(Frame,nFrameLen)) == 0)					
							strError.SynCmdRecvOver ++;
					}
				}
				else
				{
					nRvLen2 = 0;//清除当前数据
				}
				Frame += nFrameLen;		//2、3更新一次处理内Frame的值
			}
			Frame = ch[1] - nRvLen2;//重新定位Frame头指针
		}		
	}
	ThreadCtlCode = -1;
	
	
	CloseCard();
	
	return 1;
}


/* InitCard() : 初始化底层接口库 */
BOOL WINAPI InitCard(char * ServerAddr, int Port, char * Name, char * Passwd)
{
	char str;
	//test
	//ThreadCtlCode = 1;
	//AfxBeginThread(ThreadProc,&str);//,THREAD_PRIORITY_TIME_CRITICAL);
	//return TRUE;
	//如果重复调用,则先停止底层
	if(bBeRun)
	{
		if(CloseCard() == FALSE)
			return FALSE;
	}
	
	//初始化socket
	WSADATA wsd;
	if(WSAStartup(MAKEWORD(2,2),&wsd) != 0)
	{
		//Fail to load winsock
		return FALSE;
	}
	
	
	//建立socket连接

    struct sockaddr_in	serverAddr;	/* server's address */
	struct hostent *host = NULL;


    /* Zero out the sock_addr structures.
     * This MUST be done before the socket calls.
     */

    memset(&serverAddr, 0, sizeof (serverAddr));    

    /* Open the socket.
     * Use ARPA Internet address format and stream sockets.
     */

    sClient = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
	int sockopt = 1;
	setsockopt( sClient, IPPROTO_TCP, SO_KEEPALIVE, (char *)&sockopt,sizeof(int));

    if (sClient == INVALID_SOCKET)
	{
		sClient = 0;
		return FALSE;
	}

    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = inet_addr(ServerAddr);
	serverAddr.sin_port = htons(Port);	
	if(connect(sClient,(struct sockaddr *)&serverAddr,
		sizeof(serverAddr)) == SOCKET_ERROR)
	{
//		closesocket(sClient);
//		sClient = 0;
		CloseCard();
		return FALSE;
	}
	//版本协商和身份验证
	//构造发送数据,验证通过以后继续下一步
//临时发送任意数据
	
	str = 'a';
	if(sClient)
		send(sClient,&str, 1,0);

	if(hMutexSend == NULL)
		hMutexSend = CreateMutex(NULL,FALSE,NULL);
	if(pBufDataRecv == 0)
		pBufDataRecv = new class CBuffer(BUFDATASIZE,BUFRECVDATANUM,TRUE);
/*	if(pBufDataSend == 0)
		pBufDataSend = new class CBuffer(BUFDATASIZE,BUFSENDDATANUM,TRUE);
*/
	if(pBufSynCmdRecv == 0)
		pBufSynCmdRecv = new class CBuffer(BUFCMDSIZE,BUFRECVSYNCMDNUM,TRUE,1000);
	if(pBufAsyCmdRecv == 0)
		pBufAsyCmdRecv = new class CBuffer(BUFCMDSIZE,BUFRECVASYCMDNUM,TRUE);
/*	if(pBufCmdSend == 0)
		pBufCmdSend = new class CBuffer(BUFCMDSIZE,BUFSENDCMDNUM,TRUE);
*/

	hEvent[0] = WSACreateEvent();//创建一个事件
	hEvent[1] = CreateEvent(NULL,FALSE,FALSE,NULL);//开始时不激活
	unsigned char Message[64];

	ThreadCtlCode = 1;
	AfxBeginThread(ThreadProc,&str);//,THREAD_PRIORITY_TIME_CRITICAL);
	while(bBeRun == 0)
		Sleep(100);
	//WSAEventSelect(sClient,hEvent[0],FD_READ | FD_CLOSE);//将事件与套接字关联

//	bBeRun = 1;//标志底层开始工作
	return TRUE;
}



BOOL WINAPI CloseCard()           //stop the process(MyThreadProc)         
{
	static bool bOnce = false;
	if(bOnce)//防止重入
		return TRUE;
	bOnce = true;
	if(sClient){closesocket(sClient); sClient = 0;}
	if(bBeRun == 0)
	{
		bOnce = false;
		return TRUE;
	}
	char trynums = 0;
	if(ThreadCtlCode > 0)	//if running
	{
		ThreadCtlCode = 0;	//stop running
		SetEvent(hEvent[1]);
		if(sClient){closesocket(sClient); sClient = 0;}
		while((ThreadCtlCode != -1))//&&(trynums<20));//等待线程终止
		{
			Sleep(10);
			trynums++;
		}
	}
	if(ThreadCtlCode > 0)
	{
		bOnce = false;
		return FALSE;
	}
	
	if(pBufDataRecv){delete(pBufDataRecv); pBufDataRecv = 0;}
//	if(pBufDataSend){delete(pBufDataSend); pBufDataSend = 0;}
	if(pBufSynCmdRecv){delete(pBufSynCmdRecv); pBufSynCmdRecv = 0;}
	if(pBufAsyCmdRecv){delete(pBufAsyCmdRecv); pBufAsyCmdRecv = 0;}
//	if(pBufCmdSend){delete(pBufCmdSend); pBufCmdSend = 0;}

	if(hMutexSend){CloseHandle(hMutexSend); hMutexSend = NULL;}
//	if(sClient){closesocket(sClient); sClient = 0;}
	WSACleanup();
	if(hEvent[0] != 0)
		WSACloseEvent(hEvent[0]);
	if(hEvent[1] != 0)
		CloseHandle(hEvent[1]);
	bBeRun = 0;
	bOnce = false;
	return TRUE;
}

/***************** 停止读取数据 *************/
/********************************************/
int WINAPI ReadCardUnlock()
{
	if(!bBeRun)return -2;
	return (pBufDataRecv->Unlock());
}
/************ReadCard()--读数据****************************
data:存放数据,ych:存放异常帧(0:无,1:超短,2:CRC错,3:不完整 以不同的位显示)
返回值:读出的数据字节数
***********************************************************/
int WINAPI ReadCard(unsigned char *data, int size, 
					unsigned char *chanel, unsigned char * group, 
					unsigned char *abnormal,unsigned int * pTime, unsigned char * trunc)
{ 
	if(!bBeRun)return 0;
	unsigned char temp[BUFDATASIZE];
	int nFrameLength = 0, nPackLength;
	while(1)
	{
		if((pBufDataRecv->GetFrom(temp,BUFDATASIZE)) == 0)
			return 0;
		if((temp[12] & 0x40) == 1)	//截断数据
		{
			if(trunc)
				*trunc = 1;//表示截断数据
			nPackLength = 64;
			nFrameLength = ((temp[12] & 0x1F) << 8) + temp[13];
			break;
		}
		else						//全部数据
		{
			if(trunc != NULL)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -