📄 netinterface.cpp
字号:
// NetInterface.cpp : Defines the initialization routines for the DLL.
//
#include "stdafx.h"
#include "NetInterface.h"
#include "Data.h"
#include "DataAnalysisEngine.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//
// Note!
//
// If this DLL is dynamically linked against the MFC
// DLLs, any functions exported from this DLL which
// call into MFC must have the AFX_MANAGE_STATE macro
// added at the very beginning of the function.
//
// For example:
//
// extern "C" BOOL PASCAL EXPORT ExportedFunction()
// {
// AFX_MANAGE_STATE(AfxGetStaticModuleState());
// // normal function body here
// }
//
// It is very important that this macro appear in each
// function, prior to any calls into MFC. This means that
// it must appear as the first statement within the
// function, even before any object variable declarations
// as their constructors may generate calls into the MFC
// DLL.
//
// Please see MFC Technical Notes 33 and 58 for additional
// details.
//
/////////////////////////////////////////////////////////////////////////////
// CNetInterfaceApp
BEGIN_MESSAGE_MAP(CNetInterfaceApp, CWinApp)
//{{AFX_MSG_MAP(CNetInterfaceApp)
// 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()
/////////////////////////////////////////////////////////////////////////////
// CNetInterfaceApp construction
CNetInterfaceApp::CNetInterfaceApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CNetInterfaceApp object
CNetInterfaceApp theApp;
//初始化缓冲区
void CNetInterfaceApp::InitBuffer()
{
CData *pdata;
for(int i=0;i<m_nBufferNum;i++)
{
pdata=new CData;
m_read_data_list.AddTail(pdata);
pdata=new CData;
m_send_data_list.AddTail(pdata);
}
m_nextBlank_sendData=m_send_data_list.GetHeadPosition();
m_nextUnanalysised_readData=m_nextBlank_readData=m_read_data_list.GetHeadPosition();
}
//释放缓冲区
void CNetInterfaceApp::UnInitBuffer()
{
CData *pdata=NULL;
POSITION pos;
pos=m_send_data_list.GetHeadPosition();
while(pos)
{
pdata=m_send_data_list.GetNext(pos);
delete pdata;
pdata=NULL;
}
m_send_data_list.RemoveAll();
pos=m_read_data_list.GetHeadPosition();
while(pos)
{
pdata=m_read_data_list.GetNext(pos);
delete pdata;
pdata=NULL;
}
m_read_data_list.RemoveAll();
}
//得到下一个可用缓冲区节点
CData* CNetInterfaceApp::GetNextBlankBuffer(DataList &m_list, POSITION&nextBlank)
{
CData *pdata=NULL;
pdata=m_list.GetNext(nextBlank);
if(nextBlank==NULL)
{
m_criticalSection.Lock();//因为可能会申请新的内存,加到链表上,所以保护一下
nextBlank=m_list.AddTail(new CData);
m_criticalSection.Unlock();
}
pdata->Init();
return pdata;
}
//得到下一个有数据的缓冲区节点
CData* CNetInterfaceApp::GetNextBuffer(DataList &m_list,POSITION next)
{
CData *pdata=NULL;
if(next!=m_list.GetHeadPosition())
{
pdata=m_list.RemoveHead();
m_list.AddTail(pdata);
}
return pdata;
}
//得到下一个没有分析数据的缓冲区节点
CData* CNetInterfaceApp::GetNextUnanalysisedBuffer()
{
CData *pdata=NULL;
if(m_nextUnanalysised_readData!=m_nextBlank_readData)
{
pdata=m_read_data_list.GetNext(m_nextUnanalysised_readData);
}
return pdata;
}
//如果分析接收到的数据时,发现接收到的数据是非法的,就用这个函数扔掉这个数据,
//同时,将这个接收缓冲区节点移到接收缓冲区的尾端。
void CNetInterfaceApp::AbandonData()
{
POSITION tempPos=m_nextUnanalysised_readData;
m_read_data_list.GetPrev(tempPos);
CData *pdata=m_read_data_list.GetAt(tempPos);
m_criticalSection.Lock();//把此节点放到链表的最后,需要保护
m_read_data_list.RemoveAt(tempPos);
m_criticalSection.Unlock();
m_read_data_list.AddTail(pdata);
}
//写LOG文件
void CNetInterfaceApp::AddMessageToLogFile(CString strLogMessage)
{
m_strErrorMessage=strLogMessage;
static CString logDate="";
CTime tm=CTime::GetCurrentTime();
CString strTime=tm.Format("%Y-%m-%d");
if(logDate!=strTime)logDate=strTime;
CString strLogFileName;
strLogFileName.Format("NetInterface[%s].log",logDate);
CFile f;
if(!f.Open(strLogFileName,CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite))
return;
try
{
strTime=tm.Format("[%Y-%m-%d %H:%M:%S]");
strLogMessage=strTime+strLogMessage+_T("\r\n");
f.SeekToEnd();
f.Write((LPTSTR)(LPCTSTR)strLogMessage,strLogMessage.GetLength());
f.Close();
}
catch(CFileException *e)
{
f.Close();
e->Delete();
}
}
//读取数据线程函数,lParam为CNetInterfaceApp对象指针
UINT CNetInterfaceApp::ReadDataThread(LPVOID lParam)
{
CNetInterfaceApp *pApp=(CNetInterfaceApp*)lParam;
WSAEVENT hEvent[2];
hEvent[0]=EventArray[EVENT_BEGIN_READ]; //有数据到来
hEvent[1]=EventArray[EVENT_CLOSE_READ_THREAD]; //主程序关闭读取数据线程
pApp->AddMessageToLogFile("读取数据线程启动成功!");
BOOL bQuit=FALSE;
while(!bQuit)
{
//等待信号
DWORD dwRet=WaitForMultipleObjects(2,hEvent,FALSE,WSA_INFINITE)-WSA_WAIT_EVENT_0;
switch(dwRet)
{
case 0://有数据到来,从接收缓冲中取出一个节点,将数据直接放到接收缓冲区中
{
//恢复数据到来信号为没有数据状态
WSAResetEvent(EventArray[EVENT_BEGIN_READ]);
//得到一个缓冲区节点
POSITION tempPos=m_nextBlank_readData;
CData *pdata=pApp->GetNextBlankBuffer(m_read_data_list,tempPos);
if(pApp->_ReadData(pdata,m_read_client_sockaddr_in))
{
m_nextBlank_readData=tempPos;
//通知数据处理线程
WSASetEvent(EventArray[EVENT_DATA_PROCESS]);
}
}
break;
case 1://主程序关闭读取数据线程
{
bQuit=TRUE;
pApp->AddMessageToLogFile("主程序关闭接收数据线程");
}
break;
default://未知道错误
{
pApp->AddMessageToLogFile("[WaitForMultipleObjects]发生未知道错误");
}
break;
}
}
//通知主程序,读取数据线程已经关闭了
pApp->AddMessageToLogFile("读取数据线程退出了!");
WSASetEvent(EventArray[EVENT_READ_THREAD_END]);
return 0;
}
//分析接收到的数据
UINT CNetInterfaceApp::DataAnalysisThread(LPVOID lParam)
{
CNetInterfaceApp *pApp=(CNetInterfaceApp*)lParam;
BOOL bQuit=FALSE;
DWORD dwRet;
WSAEVENT hEvent[2];
pApp->AddMessageToLogFile("分析数据线程启动成功!");
hEvent[0]=EventArray[EVENT_DATA_PROCESS]; //有数据到来
hEvent[1]=EventArray[EVENT_CLOSE_DATA_PROCESS_THREAD]; //主程序关闭线程
while(!bQuit)
{
dwRet=WaitForMultipleObjects(2,hEvent,FALSE,WSA_INFINITE)-WSA_WAIT_EVENT_0;
if(dwRet==0)
{
WSAResetEvent(EventArray[EVENT_DATA_PROCESS]);
CData *pdata=pApp->GetNextUnanalysisedBuffer();
while(pdata!=NULL)
{
if(m_pDataEngine->DisComposeData(pdata))
{
PostMessage(m_hUserProgramWnd,WM_NEW_MESSAGE,0,0);
pApp->AddMessageToLogFile("收到合法数据,已通知应用层");
}
else
{
pApp->AbandonData();
pApp->AddMessageToLogFile("收到不合法数据,数据被丢掉");
}
pdata=pApp->GetNextUnanalysisedBuffer();
}
}
else if(dwRet==1)
{
bQuit=TRUE;
}
else
{
pApp->AddMessageToLogFile("数据分析线程出现未知错误,程序继续运行");
}
}
pApp->AddMessageToLogFile("数据分析线程退出了!");
WSASetEvent(EventArray[EVENT_DATA_PROCESS_THREAD_END]);
return 0;
}
//发送数据线程函数,lParam为CNetInterfaceApp对象指针
UINT CNetInterfaceApp::SendDataThread(LPVOID lParam)
{
CNetInterfaceApp *pApp=(CNetInterfaceApp*)lParam;
DWORD dwRet;
HANDLE hEvent[2];
hEvent[0]=EventArray[EVENT_CLOSE_SEND_THREAD]; //主程序关闭发送数据线程
hEvent[1]=EventArray[EVENT_BEGIN_SEND]; //开始发送数据线程
pApp->AddMessageToLogFile("发送数据线程启动成功!");
BOOL bQuit=FALSE;
while(!bQuit)
{
CData *pdata=pApp->GetNextBuffer(m_send_data_list,m_nextBlank_sendData);
while(pdata!=NULL)
{
pApp->_SendData(pdata,m_send_client_sockaddr_in);
pdata=pApp->GetNextBuffer(m_send_data_list,m_nextBlank_sendData);
}
//发送数据线程暂停
pApp->AddMessageToLogFile("所有数据都发送完了,发送过程暂停");
//等待启动发送数据过程或退出信号:0,退出,1,启动发送数据过程
//发送数据线程在没有数据需要发送时,会停止在这里
dwRet=WaitForMultipleObjects(2,&hEvent[0],FALSE,WSA_INFINITE)-WSA_WAIT_EVENT_0;
if(0==dwRet)//退出EVENT_CLOSE_SEND_THREAD
{
bQuit=TRUE;
}
else if(1==dwRet)//EVENT_END_SEND
{
//恢复启动发送数据过程的信号
WSAResetEvent(EventArray[EVENT_BEGIN_SEND]);
//继续下一轮发送过程
pApp->AddMessageToLogFile("接收到发送消息,发送过程启动");
}
}
//通知主程序,发送数据线程已经关闭了
pApp->AddMessageToLogFile("发送数据线程退出了!");
WSASetEvent(EventArray[EVENT_SEND_THREAD_END]);
return 0;
}
BOOL CNetInterfaceApp::_ReadData(CData *pdata, SOCKADDR_IN &addr)
{
BOOL bRet=TRUE;
WSABUF wsbuf;
WSAOVERLAPPED overlapped;
DWORD dwFlags;
DWORD dwPendingRet;
int nRet,error;
CString strMessage;
BOOL pending;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -