📄 carditfa.cpp
字号:
/****************************************************
* 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 + -