class CIOCPServer
{
CString m_sConnectString;
public:
CDatabase m_Database;
/*读起用户信息到内存*/
CIOCPServer();
virtual ~CIOCPServer();
//2005.6.2
BOOL StartServer();
BOOL StopServer();
BOOL InitSocket(SOCKET_STYPE stype,int port, int num = -1);
//绑定在端口上工作线程
static DWORD WINAPI CompletionWorkerThread( void * lpParam);
private:
BOOL ProcessLoadMsg(LPCLIENTCONTEXT lpContext);
private:
//根据消息overlapped的类型,处理消息
BOOL ProcessIOMessage(SOCKET_STYPE stype,IOType opCode, LPCLIENTCONTEXT lpContext , DWORD dwIoSize);
//在端口上产生线程,并创建完成端口
void CreateWorkerThread();
//关闭完成端口
void CloseCompletionPort();
//分配连接overlappedplus
LPOVERLAPPEDPLUS AllocateOverlappedPlus(IOType ioType);
//分配连接进入的客户的相关信息
LPCLIENTCONTEXT AllocateContext();
//释放overlappedplus
void FreeOverlappedPlus(LPOVERLAPPEDPLUS lpOlp);
private:
HANDLE m_hIocp; //完成端口句柄
DWORD m_dwThreads; //线程数
};
CPP方式:
#include "IOCPServer.h"
#include "common.h"
CIOCPServer::CIOCPServer()
{
//socket初始化
WSADATA wsd;
WORD wVersionRequested = MAKEWORD(2, 2);
int nResult = WSAStartup(wVersionRequested, &wsd);
if (nResult == SOCKET_ERROR)
{
WSACleanup();
}
if (LOBYTE(wsd.wVersion) != 2 || HIBYTE(wsd.wVersion) != 2)
{
WSACleanup();
}
}
CIOCPServer::~CIOCPServer()
{
WSACleanup();
}
//分配连接overlappedplus
LPOVERLAPPEDPLUS CIOCPServer::AllocateOverlappedPlus(IOType ioType)
{
OVERLAPPEDPLUS* pOlp = NULL;
pOlp = new OVERLAPPEDPLUS;
ZeroMemory(pOlp, sizeof(OVERLAPPEDPLUS));
pOlp->opCode = ioType;
return pOlp;
}
//分配连接进入的客户的相关信息
LPCLIENTCONTEXT CIOCPServer::AllocateContext()
{
LPCLIENTCONTEXT lpContext = NULL;
lpContext = new CLIENTCONTEXT;
ZeroMemory(lpContext, sizeof(CLIENTCONTEXT));
lpContext->m_wsaBuffer.buf = lpContext->m_Buffer;
lpContext->m_wsaBuffer.len = BUFSIZE;
return lpContext;
}
//释放overlappedplus
void CIOCPServer::FreeOverlappedPlus(LPOVERLAPPEDPLUS lpOlp)
{
delete lpOlp;
}
//根据消息overlapped的类型,处理消息,返回值TRUE:继续读,FALSE,不读
//一般写事件就不让他都返回FALSE,没有必要再读了!
BOOL CIOCPServer::ProcessIOMessage(SOCKET_STYPE stype,IOType opCode, LPCLIENTCONTEXT lpContext , DWORD dwIoSize)
{
BOOL bRet = FALSE;
//根据stype确定操作
switch (stype)
{
case LOAD_SOCKET:
ProcessLoadMsg(lpContext);
break;
}
return TRUE;
}
//关闭完成端口
void CIOCPServer::CloseCompletionPort( )
{
PostQueuedCompletionStatus(m_hIocp, 0, (DWORD) NULL, NULL);
// Close the CompletionPort and stop any more requests
CloseHandle(m_hIocp);
}
void CIOCPServer::CreateWorkerThread()
{
SYSTEM_INFO sysinfo;
DWORD dwThreadId;
//在completion port上等待的线程数为:CPU*2+2
GetSystemInfo(&sysinfo);
m_dwThreads = sysinfo.dwNumberOfProcessors*2+2;
for(UINT i=0;i {
HANDLE hThread;
hThread = CreateThread(NULL,
0,
CompletionWorkerThread,
(LPVOID)this,
0,
&dwThreadId);
CloseHandle(hThread);
}
//产生完成端口
m_hIocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
if(m_hIocp == NULL)
{
return;
}
}
//绑定在端口上工作线程
DWORD WINAPI CIOCPServer::CompletionWorkerThread( void * lpParam)
{
CIOCPServer *pIocpServer = (CIOCPServer *)lpParam;
DWORD dwNumRead;
LPCLIENTCONTEXT lpContext;
LPWSAOVERLAPPED lpOverlapped;
LPOVERLAPPEDPLUS lpOlp;
while (TRUE)
{
BOOL bError = FALSE;
BOOL bEnterRead = TRUE;
BOOL bResult = GetQueuedCompletionStatus(pIocpServer->m_hIocp,
&dwNumRead,
(LPDWORD)&lpContext,
&lpOverlapped,
INFINITE);
//获得LPOVERLAPPEDPLUS指针
lpOlp = CONTAINING_RECORD(lpOverlapped, OVERLAPPEDPLUS, ol);
if (dwNumRead == 0){
return 0;
}
//非timeout引起的错误, 相关信息没有从GetQueuedCompletionStatus中返回
if (!bResult && lpOlp == NULL && WAIT_TIMEOUT != WSAGetLastError())
{
// 发生错误
bError = TRUE;
}
//错误,但是相关信息从GetQueuedCompletionStatus中返回
//可能原因之一是:客户强制退出了!
else if(!bResult && lpOlp != NULL)
{
//循环继续,不应该读了!
continue;
}
//无错误,处理事件
if (!bError)
{
if(bResult && NULL != lpOlp && NULL != lpContext)
{
bEnterRead = pIocpServer->ProcessIOMessage(lpContext->m_stype,lpOlp->opCode, lpContext, dwNumRead);
}
}
//重新初试化
if(! bError && bEnterRead)
{
LPOVERLAPPEDPLUS lpOlp = pIocpServer->AllocateOverlappedPlus(OP_IORead);
ULONG ulFlags = MSG_PARTIAL;
ZeroMemory(lpContext->m_wsaBuffer.buf, lpContext->m_wsaBuffer.len);
int len = sizeof(sockaddr_in);
UINT nRetVal = WSARecvFrom(lpContext->m_Socket,
&lpContext->m_wsaBuffer,
1,
0,
&ulFlags,
(sockaddr*)&lpContext->m_fromaddr,&len,
&lpOlp->ol,
NULL);
if ( nRetVal == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING)
return FALSE;
}
pIocpServer->FreeOverlappedPlus(lpOlp);
}
return 0;
}
BOOL CIOCPServer::InitSocket(SOCKET_STYPE stype,int port,int num)
{
//bind SOCKET to completion port and init first work
LPCLIENTCONTEXT LoadListenData = AllocateContext();
if (LoadListenData == NULL)
return FALSE;
LoadListenData->m_Socket = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED);
if(LoadListenData->m_Socket == SOCKET_ERROR)
return FALSE;
//需要绑定的本地地址
sockaddr_in local;
memset(&local, 0, sizeof(local));
local.sin_addr.s_addr = htonl(INADDR_ANY);
local.sin_family = AF_INET;
local.sin_port = htons(port);
//绑定,将监听端口绑定到本地地址
if(bind(LoadListenData->m_Socket, (sockaddr*)&local,sizeof(local))
== SOCKET_ERROR)
return FALSE;
LoadListenData->m_stype = stype;
LoadListenData->m_nNum = num;
HANDLE hrc = CreateIoCompletionPort((HANDLE)LoadListenData->m_Socket,m_hIocp,(DWORD)LoadListenData,0);
if (NULL == hrc)
return FALSE;
int len = sizeof(sockaddr_in);
LPOVERLAPPEDPLUS lpOlp = AllocateOverlappedPlus(OP_IORead);
ULONG ulFlags = MSG_PARTIAL;
int iret = WSARecvFrom(LoadListenData->m_Socket,
&(LoadListenData->m_wsaBuffer),
1,NULL,
&ulFlags,
(sockaddr*)&LoadListenData->m_fromaddr,&len,
&lpOlp->ol,
NULL
);
if (iret == SOCKET_ERROR && WSAGetLastError() != ERROR_IO_PENDING)
return FALSE;
return TRUE;
}
BOOL CIOCPServer::StartServer()
{
m_Database.OpenEx("DSN=SASSYSTEM;UID=;PWD=");
CreateWorkerThread();
if(!InitSocket(LOAD_SOCKET,14688))
AfxMessageBox("fair");
return TRUE;
}
BOOL CIOCPServer::StopServer()
{
CloseCompletionPort();
return TRUE;
}
BOOL CIOCPServer::ProcessLoadMsg(LPCLIENTCONTEXT lpContext)
{
//lpContext->m_Buffer就是你接收到的数据信息了
//调试信息
/* char buf[200];
memset(buf,0,sizeof(buf));
memcpy(buf,lpContext->m_Buffer,200);
FILE * file;
file=fopen("BUF内容.txt","w");
for(int i=0;i<100;i++)
{
fprintf(file,"%s",buf+i);
}
fprintf(file,"over");
fclose(file);
*/
return TRUE;
}