socketCompletePort.h
/********************************************************************
创建时间: 2013/04/11
文件名: socketCompletePort.h
描述:
完成端口I/O模型
作者: fengsh
QQ : 19985430
电子邮件: fengsh998@163.com
Blog : http://blog.csdn.net/fengsh998
@CopyRight fengsh
*********************************************************************/
#pragma once
#include "socketbase.h"
#include "socketArrays.h"
typedef enum IOCP_WITH_TYPE {cpNone,cpRead,cpWrite};
typedef struct tagIOCP
{
WSAOVERLAPPED overlap;
WSABUF Buffer;
char buf[BUFFERMAX];
DWORD dwNumOfBytesRecved;
DWORD Flags;
IOCP_WITH_TYPE type;
}PER_IOCP_DATA,*LPPER_IOCP_DATA;
class CSocketCompletePort :
public CSocketBase
{
private:
bool initCompletionPort();
int getSysProcessNum();
public:
CSocketCompletePort(void);
~CSocketCompletePort(void);
int startServer() ;
int stopServer() ;
bool sendtext(const std::string& content) ;
void doIOCP(SOCKET client);
void closeIOCP();
LPPER_IOCP_DATA m_iocpdata;
HANDLE m_completionport;
private:
void *wcid;
void *tid;
CSocketArrays *clients;
};
socketCompletePort.cpp
#include "socketCompletePort.h"
#include "socketThread.h"
static void* wait_client_thread(void* param);
static void* with_iocp_thread(void* param);
CSocketCompletePort::CSocketCompletePort(void)
{
m_completionport = INVALID_HANDLE_VALUE;
m_iocpdata = NULL;
clients = new CSocketArrays();
}
CSocketCompletePort::~CSocketCompletePort(void)
{
delete clients;
}
bool CSocketCompletePort::initCompletionPort()
{
m_completionport = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
if (m_completionport==NULL)
{
//创建完成端口失败!GetLastError());
return false;
}
else
return true;
//printf("创建完成端口成功!");
}
int CSocketCompletePort::getSysProcessNum()
{
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
return sysInfo.dwNumberOfProcessors;
}
int CSocketCompletePort::startServer()
{
if (initSocket() && initCompletionPort())
{
socket_thread_create(&wcid,wait_client_thread,(void*)this);
int threadnum = getSysProcessNum();
for (int i = 0; i < threadnum; i++)
{
socket_thread_create(&tid,with_iocp_thread,(void*)this);
}
}
return -1;
}
int CSocketCompletePort::stopServer()
{
dispatchcallback(cbServerClose,NULL);
clients->clear();
closesocket(m_listenSocket);
return 1;
}
bool CSocketCompletePort::sendtext( const std::string& content )
{
for (int i = 0 ;i < clients->count();i++)
{
//need to sure clients is valid.
sendData(clients->getSocketByIndex(i),content);
}
return true;
}
void CSocketCompletePort::doIOCP( SOCKET client )
{
clients->addSocket(client);
CreateIoCompletionPort((HANDLE)client,m_completionport,(DWORD)client,0);
m_iocpdata = (LPPER_IOCP_DATA)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,sizeof(PER_IOCP_DATA));
m_iocpdata->Buffer.len=BUFFERMAX;
m_iocpdata->Buffer.buf=m_iocpdata->buf;
m_iocpdata->type = cpRead;
WSARecv(client,&m_iocpdata->Buffer,1,
&m_iocpdata->dwNumOfBytesRecved,&m_iocpdata->Flags,
&m_iocpdata->overlap,NULL);
}
void CSocketCompletePort::closeIOCP()
{
PostQueuedCompletionStatus(m_completionport,0xFFFFFFFF,0,NULL);
CloseHandle(m_completionport);
}
static void* wait_client_thread(void* param)
{
CSocketCompletePort *iocp = (CSocketCompletePort*)param;
DISPATCHPARAM dp;
memset(&dp,0,sizeof(DISPATCHPARAM));
SOCKET socketClient;
while(true)
{
SOCKADDR_IN addrClient;
int addrClientSize=sizeof(SOCKADDR_IN);
socketClient=accept(iocp->m_listenSocket,(struct sockaddr*)&addrClient,&addrClientSize);
if (socketClient==INVALID_SOCKET)
{
socketClient = NULL;
if (iocp->checkSocketError(WSAGetLastError()))
{
break;
}
continue;
}
else
{
iocp->doIOCP(socketClient);
strcpy(dp.info.ip,inet_ntoa(addrClient.sin_addr));
dp.info.port = addrClient.sin_port;
iocp->dispatchcallback(cbHasConnect,&dp);
}
}
iocp->closeIOCP();
return 0;
}
static void* with_iocp_thread(void* param)
{
CSocketCompletePort *iocp = (CSocketCompletePort*)param;
DISPATCHPARAM dp;
memset(&dp,0,sizeof(DISPATCHPARAM));
HANDLE CompletionPort = iocp->m_completionport;
DWORD dwByteTransferred;
SOCKET socketClient;
LPPER_IOCP_DATA lpPerIOData = NULL;
while(true)
{
GetQueuedCompletionStatus(CompletionPort,&dwByteTransferred,
(PULONG_PTR)&socketClient,(LPWSAOVERLAPPED *)&lpPerIOData,INFINITE);
if (dwByteTransferred == 0xFFFFFFFF)
{
return 0;
}
if (lpPerIOData->type == cpRead)
{
if (dwByteTransferred == 0)
{
closesocket(socketClient);
HeapFree(GetProcessHeap(),0,lpPerIOData);
}
else
{
strcpy(dp.msg,lpPerIOData->buf);
//回调到界面
iocp->dispatchcallback(cbCommunication,&dp);
//回调到接收完成
iocp->dispatchcallback(cbRecviced,NULL);
memset(&lpPerIOData->overlap,0,sizeof(WSAOVERLAPPED));
lpPerIOData->Buffer.len = BUFFERMAX;
lpPerIOData->Buffer.buf = lpPerIOData->buf;
lpPerIOData->type = cpRead;
WSARecv(socketClient,&lpPerIOData->Buffer,1,
&lpPerIOData->dwNumOfBytesRecved,&lpPerIOData->Flags,
&lpPerIOData->overlap,NULL);
}
}
}
return 0;
}