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

📄 netinterface.cpp

📁 用事件方式
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -