您的位置:首页 > 理论基础 > 计算机网络

TCP 完成端口服务器构建

2013-11-23 14:06 155 查看
在vs2008中编译通过,vs2010应该也没有问题。

使用静态MFC dll。

其他配置保持默认即可。

可能需要设置/MTD运行时。

可以实现向指定客户端ip发送信息

(该客户端必须首先连接进服务器)

从指定客户端ip中取出数据。

我使用C++类进行了封装,

对各种异常进行了处理。

进行了较详细的注释,

如果有函数不清楚,可以去msdn上查一查。

1,客户端类

#pragma once

#define RECEIVE_SIZE 1024
/****************************************************
//Client
function :
  save info of client
***************************************************/
class Client
{
public:
	Client();
	~Client();
public:
	CCriticalSection	m_cs;

	BYTE				m_pRemainBuf[RECEIVE_SIZE];                 //数据缓存区 
	BYTE				m_nDataLen;					//数据缓冲区中已有数据的长度
	BYTE				m_pReceBuf[RECEIVE_SIZE];                   //接受到的数据
	OVERLAPPED			m_OverLapped;

	WSABUF				m_DataBuf; 
	SOCKADDR_IN			m_ClientAddress;

	//[!if NET_TYPE_TCP]
	SOCKET				m_hClientSock;							  //communication socket;
	//[!endif]

public:
	//***********将数据存入Client对应的缓冲区中*******************
	BOOL	SetData(int len);

	//***********从Client对应的缓冲区中取出数据*******************
	int		GetData(char * buff, int len);
};


实现:

#include "stdafx.h"
#include "Client.h"

/****************************************************************************
*   Name
Client
*	Type
public
*	Function
construction function
*	Return Value
null
*	Parameters
null
*****************************************************************************/
Client::Client()
{
	//[!if NET_TYPE_TCP]
	m_hClientSock = INVALID_SOCKET;
	//[!endif]

	m_nDataLen = 0;
	memset(m_pRemainBuf, 0, RECEIVE_SIZE);
	memset(m_pReceBuf,0,RECEIVE_SIZE);
	memset(&m_OverLapped, 0, sizeof(m_OverLapped));
}

/****************************************************************************
*   Name
~Client
*	Type
public
*	Function

*	Return Value
null
*	Parameters
null
*****************************************************************************/
Client::~Client()
{
	int a=0;
	a=3;
}

//*********************TCP接受数据************************
//**************缓冲区没有溢出,则将数据追加其后**********
BOOL Client::SetData( int len )
{
	if (len<0)
	{
		return FALSE;
	}

	if (len==0)
	{
		return TRUE;
	}

	m_cs.Lock();
	if (m_nDataLen+len>=RECEIVE_SIZE)
	{
		if (len<RECEIVE_SIZE)
		{
			memcpy_s(m_pRemainBuf, RECEIVE_SIZE, m_pReceBuf, len);
			m_nDataLen = len;
		}
		else
		{
			memcpy_s(m_pRemainBuf, RECEIVE_SIZE, m_pReceBuf, RECEIVE_SIZE);
			m_nDataLen = (BYTE)RECEIVE_SIZE;
		}
	}
	else
	{
		memcpy_s(m_pRemainBuf + m_nDataLen, RECEIVE_SIZE-m_nDataLen, m_pReceBuf, len);
		m_nDataLen += len;
	}

	m_cs.Unlock();

	return TRUE;
}

int Client::GetData( char * buff, int len )
{
	if (!buff)
	{
		return 0;
	}

	int result=0;
	m_cs.Lock();
	if (m_nDataLen <= len)
	{
		memcpy_s(buff, len, m_pRemainBuf, m_nDataLen);
		result = m_nDataLen;
		m_nDataLen = 0;
	}
	else
	{
		memcpy_s(buff, len, m_pRemainBuf, len);
		memmove_s(m_pRemainBuf, RECEIVE_SIZE, m_pRemainBuf + len, m_nDataLen-len);
		m_nDataLen -= len;
		result = len;
	}
	
	m_cs.Unlock();
	return result;
}


2,TCP完成端口的封装

头文件:

/************************************************************************/
//* 文件名称: IOCP_TCP.h
//* 文件标示:
//* 摘    要:采用完成端口技术处理网络数据
//*
//* 当前版本:1.0
//* 作    者:hxy
//* 完成日期:2013-11-16
//*
/************************************************************************/
#ifndef  _COMPLETIONPORT_H__
#define  _COMPLETIONPORT_H__

#include <winsock2.h>
#include <mswsock.h>
#include "afxmt.h"
#include <vector>
#include "Client.h"
using namespace std;
#pragma once

#define MAXTHREAD_COUNT 8
#define RECEIVE_SIZE  1024
#define PORT 502

class Client;
class CompletionPort
{
public:
	CompletionPort();
	~CompletionPort();

	//************初始化****************************
	//	参数:  需要绑定的ip和port
	//	功能:	初始化socket库
	//			设置需要绑定的ip和port
	//**********************************************
	BOOL Init(char * lpszHostAddress, UINT nHostPort);

	//************启动******************************
	//	功能:	1,启动监听功能; 2,生成完成端口对象
	//**********************************************
	BOOL Active(void);

	//************停止******************************
	//	功能:	停止监听功能,
	//			释放Active中的申请的所有资源
	//**********************************************
	BOOL Close(void);

	//************接受数据**************************
	//	功能:	接受指定客户端ip的数据
	//	参数:  buff:指向接受数据的缓冲区
	//			len:  缓冲区的大小
	//			ip:	  客户端ip,如192.168.31.27
	//  说明:  buff的内存由调用者提供
	//**********************************************
	int ReceiveData(char * buff, int len, char * ip);

	//************发送数据***************************
	//	功能:	向指定的客户端ip的数据
	//	参数:  buff:指向发送数据的缓冲区
	//			len:  缓冲区的大小
	//			ip:	  客户端ip,如192.168.31.27
	//**********************************************
	int SendData(const char * buff, int len, char * ip);

//-------------------------内部使用--------------------------------
	//************监听*******************************
	//	功能:	监听客户端连接线程
	//***********************************************
	void MonitorServerSocket();	

	//************监听客户端发送的数据***************
	//	功能:	监听客户端连接线程函数
	//***********************************************
	void MonitorIoCompletionPort();							

	//************处理客户端连接*********************
	//	功能:	客户端连接处理函数
	//***********************************************
	void OnClientAccept();									

	//************处理客户端关闭*********************
	//	功能:	客户端关闭处理函数
	//***********************************************
	BOOL OnClientClose(DWORD dwSockId);

private:
	//************初始化Socket库*********************
	//	功能:	初始化Socket库
	//***********************************************
	BOOL InitWinsock();
	

	void ProcessData(Client* pClient);

	Client* GetClient(DWORD dwSockId, int& index);

//----------------------------Client 管理-------------------------

	//************增加客户端*********************
	BOOL AddClient( Client * const pClient);

	//************删除客户端*********************
	BOOL DeleteClient( int index);

	//************查询客户端*********************
	Client * GetClient( const char * ip);

private:
	
	SOCKADDR_IN m_HostAddress;							//服务器端地址(ip,port,协议)等

	vector<Client*> m_ClientVector;						//客户端表
	rec_lock m_cs;								//客户端表同步

	BOOL			m_bIsQuit;							//退出标识
	HANDLE			m_hQuitEvent;						//退出事件句柄
	HANDLE			m_hCOP;								//完成端口句柄
	HANDLE			m_hThreadArray[MAXTHREAD_COUNT];	//接收数据线程句柄
	int				m_nThreadArray;						//接收数据线程数量

	HANDLE			m_hListen;							//监听连接线程句柄
	SOCKET			m_ListenSocket;						//监听socket

	BOOL			m_bQuitThread;						//监听线程退出标识
	WSAEVENT		m_wsaEvent;							//网络事件

};

#endif


实现文件:

#include "StdAfx.h"
#include "IOCP_TCP.h"

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

/****************************************************************************
*   Name
ThreadTcpServer
*	Type
public
*	Function
thread to monitor a socket and accept a link
*	Return Value
DWORD WINAPI
*	Parameters
void * lpParameter 
*****************************************************************************/
DWORD WINAPI ThreadTcpServer(void * lpParameter)
{
	CompletionPort* pCpPort = (CompletionPort*)lpParameter;
	
	pCpPort->MonitorServerSocket();
	return 0;
}

/****************************************************************************
*   Name
CompletionRoutine
*	Type
public
*	Function
work thread of completionport 
*	Return Value
DWORD WINAPI
*	Parameters
void * lpParameter translate a pointer of this
*****************************************************************************/
DWORD WINAPI  CompletionRoutine(void * lpParameter)
{
	CompletionPort* pCpPort = (CompletionPort*)lpParameter;

	pCpPort->MonitorIoCompletionPort();
	return 0;
}

/****************************************************************************
*   Name
CompletionPort
*	Type
public
*	Function
constructor
*	Return Value
null
*	Parameters
null 
*****************************************************************************/
CompletionPort::CompletionPort()
{
	//_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF| _CRTDBG_LEAK_CHECK_DF); 
	m_hCOP = INVALID_HANDLE_VALUE;
	m_hListen = INVALID_HANDLE_VALUE;
	for (int i=0; i< MAXTHREAD_COUNT; i++)
	{
		m_hThreadArray[i] = INVALID_HANDLE_VALUE;
	}
	m_bQuitThread = FALSE;
	m_wsaEvent = NULL;
	m_ListenSocket = INVALID_SOCKET;
	m_ClientVector.clear();
	m_bIsQuit = FALSE;
	m_hQuitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	m_nThreadArray = 0;
}

/****************************************************************************
*   Name
~CompletionPort
*	Type
public
*	Function
do sth to release memory
*	Return Value
null
*	Parameters
null 
*****************************************************************************/
CompletionPort::~CompletionPort()
{
	int i = 0;
	m_bIsQuit = TRUE;
	Sleep(10);
	if (INVALID_HANDLE_VALUE != m_hCOP)
	{
		m_bIsQuit = TRUE;
		//等待所有接受数据的线程结束
		WaitForMultipleObjects(m_nThreadArray, m_hThreadArray, TRUE, INFINITE); 
		while (INVALID_HANDLE_VALUE != m_hThreadArray[i])
		{
			CloseHandle(m_hThreadArray[i]);
			m_hThreadArray[i-1] = INVALID_HANDLE_VALUE;
			i++;
		}
		//关闭完成端口
		CloseHandle(m_hCOP);
		m_hCOP=NULL;		
	}

	// 关闭监听socket
	if (INVALID_SOCKET != m_ListenSocket)
	{
		closesocket(m_ListenSocket);
		m_ListenSocket = NULL;
	}
	
	// 关闭监听线程
	m_bQuitThread = TRUE;
	WaitForSingleObject(m_hListen, INFINITE);
	if (INVALID_HANDLE_VALUE != m_hListen)
	{
		CloseHandle(m_hListen);
		m_hListen = NULL;
	}

	WSACloseEvent(m_wsaEvent);
	m_wsaEvent = NULL;

	// 关闭客户端连接socket
	for( size_t i=0; i<m_ClientVector.size(); i++)
	{
		Client* pClient = m_ClientVector[i];
		if( pClient != NULL)
		{
			if (pClient->m_hClientSock != INVALID_SOCKET)
			{
				shutdown(pClient->m_hClientSock, 2);
				closesocket(pClient->m_hClientSock);
				pClient->m_hClientSock = INVALID_SOCKET;
			}
			delete pClient;
			pClient = NULL;
		}
	}
	CloseHandle(m_hQuitEvent);
	m_ClientVector.clear();	
}

BOOL CompletionPort::Init(char * lpszHostAddress, UINT nHostPort)
{
	if (!InitWinsock())
	{
		return FALSE;
	}
	
	m_HostAddress.sin_family = AF_INET;

	m_HostAddress.sin_addr.s_addr = inet_addr((char *)lpszHostAddress);

	if (m_HostAddress.sin_addr.s_addr == INADDR_NONE)
	{
		LPHOSTENT lphost;
		lphost = gethostbyname((char *)lpszHostAddress);
		if (lphost != NULL)
			m_HostAddress.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
		else
		{
			WSASetLastError(WSAEINVAL);
			return FALSE;
		}
	}

	m_HostAddress.sin_port = htons((u_short)nHostPort);

	return true;
}

//************启动******************************
//	功能:	启动监听功能
//**********************************************
BOOL CompletionPort::Active()
{

//-------------------------------监听连接---------------------------------------
	//创建监听Socket
	m_ListenSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED); 
	if (INVALID_SOCKET == m_ListenSocket)
	{
		return FALSE;
	}

	int nResult = bind(m_ListenSocket, (PSOCKADDR)&m_HostAddress, sizeof(m_HostAddress));
	if (SOCKET_ERROR == nResult)
	{
		closesocket(m_ListenSocket);        
		return FALSE;
	}

	nResult = listen(m_ListenSocket, 20);
	if (SOCKET_ERROR == nResult)
	{
		closesocket(m_ListenSocket);
		return FALSE;
	}

	m_wsaEvent = WSACreateEvent();
	if (NULL == m_wsaEvent)
	{
		return FALSE;
	}

	WSAEventSelect(m_ListenSocket, m_wsaEvent, FD_ACCEPT);

	//创建监听连接的线程
	m_hListen = CreateThread(NULL, 0, ThreadTcpServer, (LPVOID)this, 0, NULL);
	if (NULL == m_hListen)
	{
		return FALSE;
	}

//-------------------------------完成端口---------------------------------------
	//创建完成端口句柄
	m_hCOP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0);
	if (NULL == m_hCOP)
	{
		return FALSE;
	}

	//创建处理数据的线程
	SYSTEM_INFO SysInfo;
	GetSystemInfo(&SysInfo);
	for (int i=0; i<(int)SysInfo.dwNumberOfProcessors && (i<MAXTHREAD_COUNT); i++)
	{
		m_hThreadArray[i] = CreateThread(NULL, 0, CompletionRoutine, (LPVOID)this, 0, NULL);
		if (NULL == m_hThreadArray[i])
		{
			while (i>0)
			{
				CloseHandle(m_hThreadArray[i-1]);
				m_hThreadArray[i-1] = INVALID_HANDLE_VALUE;
				i--;
			}
			return FALSE;  
		}
		m_nThreadArray ++;
	}
	return TRUE;	
}

//************从完成端口取数据******************
//	功能: 从完成端口取数据
//  返回: 字节数,如果ip未连接则返回0
//**********************************************
int CompletionPort::ReceiveData(char * buff, int len, char * ip)
{
	if (!buff || !ip)
	{
		return 0;
	}

	Client * pClient = GetClient(ip);

	if (!pClient)
	{
		return 0;
	}

	return pClient->GetData(buff, len);
}

//************发送数据***************************
//	功能:	向指定的客户端ip的数据
//	参数:  buff:指向发送数据的缓冲区
//			len:  要发送的数据的字节数
//			ip:	  客户端ip,如192.168.31.27
//  返回:	发送的字节数,错误则返回0
//**********************************************
int CompletionPort::SendData(const char * buff, int len, char * ip)
{
	if (!buff || !ip)
	{
		return 0;
	}

	int ret =0;

	//在取得客户端指针之后,完成端口线程会删除该客户端,
	//可能造成最null指针的解引用,所有这里使用结构化异常进行处理
	__try
	{
		Client * pClient = GetClient(ip);

		if (!pClient)
		{
			return 0;
		}

		DWORD result = 0;
		ret =send(pClient->m_hClientSock, buff, len, 0);
		//int ret = WriteFile((HANDLE)pClient->m_hClientSock, buff, len, &result, NULL);
	}
	__except (EXCEPTION_EXECUTE_HANDLER) 
	{
		printf("客户端已被删除,发送失败");
	}
	return ret;
}

/****************************************************************************
*   Name
InitWinsock
*	Type
public
*	Function
initialize socket
*	Return Value
BOOL
*	Parameters
null 
*****************************************************************************/
BOOL CompletionPort::InitWinsock()
{
	WSADATA wsd;
	int nResult = WSAStartup(MAKEWORD(2,2), &wsd);
	if (0 != nResult)
	{		
		return FALSE;
	}
	return TRUE;
}

/****************************************************************************
*   Name
MonitorServerSocket
*	Type
public
*	Function
function to monitor a socket and accept a link
*	Return Value
null
*	Parameters
null 
*****************************************************************************/
void CompletionPort::MonitorServerSocket()
{
	DWORD	dwWaitCode;
	WSANETWORKEVENTS wsaNetWorkEvents;
	while( true )
	{
		if( m_bQuitThread )					//判断监听线程退出条件是否满足
		{
			SetEvent(m_hQuitEvent);
			TRACE("Monitor Server Quit\n");
			return ;
		}

		dwWaitCode = WSAWaitForMultipleEvents(1, &m_wsaEvent, FALSE, 2000, FALSE);//等待网络事件
		if(dwWaitCode != WAIT_OBJECT_0)  
			continue;

		if( SOCKET_ERROR == WSAEnumNetworkEvents(m_ListenSocket, m_wsaEvent,&wsaNetWorkEvents ))//枚举网络事件
		{
			int nErrorCode = WSAGetLastError();
			TRACE("WSAEnumNetworkEvents Error");
		}
		else
		{
			if( wsaNetWorkEvents.lNetworkEvents & FD_ACCEPT)
			{
				OnClientAccept();
			}
		}
	}
}

/****************************************************************************
*   Name
OnClientAccept
*	Type
public
*	Function
function to monitor a socket and accept a link
*	Return Value
null
*	Parameters
null 
*****************************************************************************/
void CompletionPort::OnClientAccept()
{
	
	int nSockAddrLength = sizeof(SOCKADDR_IN);
	Client* pClntData = new Client();
	pClntData->m_hClientSock = accept(m_ListenSocket,
						(struct sockaddr*)&(pClntData->m_ClientAddress),
						&nSockAddrLength);

	if (INVALID_SOCKET == pClntData->m_hClientSock)
	{
		delete pClntData;
	}

	AddClient(pClntData);

	HANDLE hCompletePort = CreateIoCompletionPort((HANDLE)pClntData->m_hClientSock, m_hCOP,
		(DWORD)pClntData->m_hClientSock,0);
	if( hCompletePort != m_hCOP)
	{
		TRACE("Create Communication CompletionPort failure!\n");
	}

	ReadFile((HANDLE)pClntData->m_hClientSock, pClntData->m_pReceBuf, RECEIVE_SIZE, NULL, 
		&pClntData->m_OverLapped);
}

/****************************************************************************
*   Name
MonitorIoCompletionPort
*	Type
public
*	Function
function to monitor completionport 
*	Return Value
void
*	Parameters
null
*****************************************************************************/
void CompletionPort::MonitorIoCompletionPort()
{
	TRACE("Begin Monitor IoPort \n");
	BOOL  bSuc       = FALSE;
	DWORD dwNumBytes = 0;
	DWORD dwKey      = -1;
	DWORD dwSockId = 0;
	LPOVERLAPPED completedOverlapped;

	int nLen =0;
	while( true )
	{
		//判断监听线程退出条件是否满足
		if( m_bIsQuit)
		{
			TRACE("Monitor IoCompletionPort Quit\n");
			SetEvent(m_hQuitEvent);
			return;
		}
		//查询完全端口状态
		dwKey = -1;
		bSuc  = GetQueuedCompletionStatus( m_hCOP, &dwNumBytes, &dwKey, &completedOverlapped, 2000);
		if (bSuc==FALSE)
		{
			int nError = WSAGetLastError();

			if (nError == WSA_WAIT_TIMEOUT)
			{
				continue;
			}
			
			if (nError == ERROR_NETNAME_DELETED)
			{
				OnClientClose(dwKey);
				continue;
			}
			TRACE("GetQueuedCompletionStatus Error: %d\n", nError);
			continue;
		}

		if (dwKey>0)
		{
			dwSockId  = dwKey;
			nLen = dwNumBytes;
			if( nLen > 0)
			{ 
				int index = -1;
				Client* pClient = GetClient(dwSockId, index);
				if( pClient == NULL)  
					continue;
				try
				{
					//Sleep(50);
					if (nLen >1024)
					{
						nLen = 1024;
						//CDebug::ShowErroMessage("接收到数据长度过长!");
					}
					
					pClient->SetData(nLen);
					//ProcessData(pClient);

					//向完全端口发送读指令,等待下一次数据
					ZeroMemory(pClient->m_pReceBuf,RECEIVE_SIZE);
			
					ReadFile((HANDLE)pClient->m_hClientSock,pClient->m_pReceBuf,RECEIVE_SIZE,NULL,&pClient->m_OverLapped);
		

				}
				catch(...)
				{
					TRACE("catch an error");
				}		
			}
			else
			{
				OnClientClose(dwSockId);
			}
		}
	}
}

/****************************************************************************
*   Name
GetClient
*	Type
public
*	Function
get a pointer to point class of  Client
*	Return Value
Client*
*	Parameters
DWORD dwSockId : socket ID
int& index: the position in the vector
*****************************************************************************/
Client* CompletionPort::GetClient(DWORD dwSockId, int& index)
{
	Client* pNewData = NULL;
	m_cs.lock();
	for (size_t i = 0; i < m_ClientVector.size(); i++)
	{
		if (m_ClientVector[i]->m_hClientSock == dwSockId)
		{
			index = i;
			pNewData = m_ClientVector[i];
			break;
		}
	}
	m_cs.unlock();	
	return pNewData;
}

/****************************************************************************
*   Name
OnClientClose
*	Type
public
*	Function
close the socket that dont translate data
*	Return Value
BOOL
*	Parameters
DWORD dwSockId: socket ID
*****************************************************************************/
BOOL CompletionPort::OnClientClose(DWORD dwSockId)
{
	int index = -1;
	Client* pClient = GetClient(dwSockId, index);
	if ((NULL != pClient) && (-1 != index))
	{
		closesocket(pClient->m_hClientSock);
		DeleteClient(index);
		pClient = NULL;
	}
	return TRUE;
}

//----------------------------Client 管理-------------------------

//************增加客户端*********************
BOOL CompletionPort::AddClient(Client * const pClient)
{
	if (!pClient)
	{
		return FALSE;
	}
	m_cs.lock();
	m_ClientVector.push_back(pClient);
	m_cs.unlock();
	return TRUE;
}

//************删除客户端*********************
BOOL CompletionPort::DeleteClient(int index)
{
	m_cs.lock();
	delete m_ClientVector[index];
	m_ClientVector.erase(m_ClientVector.begin() + index);
	m_cs.unlock();
	return TRUE;
}

//************查询客户端*********************
Client * CompletionPort::GetClient(const char * ip)
{
	Client* pNewClient = NULL;
	ULONG nAddr = inet_addr(ip); 
	m_cs.lock();
	for (size_t i = 0; i < m_ClientVector.size(); i++)
	{
		if (m_ClientVector[i]->m_ClientAddress.sin_addr.s_addr == nAddr)
		{
			pNewClient = m_ClientVector[i];
			break;
		}
	}
	m_cs.unlock();
	return pNewClient;
}


3,测试文件:

// IOCPTest.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "IOCP_TCP.h"
#include <iostream>

int _tmain(int argc, _TCHAR* argv[])
{

	CCriticalSection *p = new CCriticalSection;
	delete p;

	CompletionPort * cp = new CompletionPort();
	
	cp->Init("192.168.31.27", 4567);           //需要修改为自己的ip
	cp->Active();
	
	char buff[1024]={0};
	char recBuff[1024]={0};
	int len;
	while (true)
	{
		scanf_s("%s", buff, 1023);
		len = strlen(buff);
		cp->SendData(buff, len, "192.168.31.27");	//客户端的ip
		ZeroMemory(recBuff,1024);
		cp->ReceiveData(recBuff, 1024, "192.168.31.27");     //客户端的ip
		printf("\n%s\n", recBuff);
	}
	delete cp;
	return 0;
}


5,预编译头文件

// stdafx.h : include file for standard system include files,
//  or project specific include files that are used frequently, but
//      are changed infrequently
//

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#define _WIN32_WINNT	0x0501

#define VC_EXTRALEAN		// Exclude rarely-used stuff from Windows headers

#include <afxwin.h>         // MFC core and standard components
#include <afxext.h>         // MFC extensions

#ifndef _AFX_NO_OLE_SUPPORT
#include <afxole.h>         // MFC OLE classes
#include <afxodlgs.h>       // MFC OLE dialog classes
#include <afxdisp.h>        // MFC Automation classes
#endif // _AFX_NO_OLE_SUPPORT

#ifndef _AFX_NO_DB_SUPPORT
#include <afxdb.h>			// MFC ODBC database classes
#endif // _AFX_NO_DB_SUPPORT

#ifndef _AFX_NO_DAO_SUPPORT
#include <afxdao.h>			// MFC DAO database classes
#endif // _AFX_NO_DAO_SUPPORT

#include <afxdtctl.h>		// MFC support for Internet Explorer 4 Common Controls
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h>			// MFC support for Windows Common Controls
#endif // _AFX_NO_AFXCMN_SUPPORT

//外部库文件引用
#include <afxmt.h>
#include <afx.h>
#include <afxtempl.h>

#include <winsock2.h>
#include <memory>

//外部自定义头文件引用

//#include "Resource.h"
//#include "ICOMPro.h"
//#include "datatype.h"
//#include "Reg.h"
//#include "Debug.h"
//#include "Helper.h"

#if defined(_WIN32_WCE_CEPC) || defined(_ARM_)
#include "AtomCE.h"
#endif

//编译选项

//[!if TRYCONNECT_TRUE]
//#define _TRYCONNECT_TRUE
//[!endif]
//
//[!if TRYCONNECT_USERDEFINE]
//#define _TRYCONNECT_USEDEFINE
//[!endif]
//
//[!if TRYCONNECT_USEPACKET]
//#define _TRYCONNECT_USEPACKET
//[!endif]
//
//[!if REOPENCOM]
//#define _REOPENCOM
//[!endif]

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#include "lock.h"
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: