socketOverlappedCP.h
/********************************************************************
创建时间: 2013/04/11
文件名: socketOverlappedCP.h
描述:
重叠I/O 完成例程模式
作者: fengsh
QQ : 19985430
电子邮件: fengsh998@163.com
Blog : http://blog.csdn.net/fengsh998
@CopyRight fengsh
*********************************************************************/
#pragma once
#include "socketbase.h"
typedef struct tagOVERLAPPEDCP
{
WSAOVERLAPPED overlap;
WSABUF Buffer;
char buf[BUFFERMAX];
DWORD dwNumOfBytesRecved;
DWORD Flags;
SOCKET stClient; //比事件通知多了一个套接字
void* context; //上下文句柄
}PER_OVERLAPPEDCP_DATA,*LPPER_OVERLAPPEDCP_DATA;
class CSocketOverlappedCP :
public CSocketBase
{
public:
CSocketOverlappedCP(void);
~CSocketOverlappedCP(void);
int startServer() ;
int stopServer() ;
bool sendtext(const std::string& content) ;
void doOverlapDataListen(SOCKET client);
void destroyedOverLappedDataByIndex(int idx);
void destroyedOverLappedData();
void adjustOverlappedData(int idx);
int getIndexBySocket(SOCKET selclient);
void doOverlappedCallback(DWORD dwError,DWORD csTransferred,
LPWSAOVERLAPPED lpOverlappped,DWORD dwFlags);
LPPER_OVERLAPPEDCP_DATA m_overdata[MAXIMUM_WAIT_OBJECTS];
int m_count;
private:
void *wcid;
};
socketOverlappedCP.cpp
#include "socketOverlappedCP.h"
#include "socketThread.h"
void CALLBACK CompletionCallBack(DWORD dwError,DWORD csTransferred,
LPWSAOVERLAPPED lpOverlappped,DWORD dwFlags);
static void* wait_client_thread(void* param);
CSocketOverlappedCP::CSocketOverlappedCP(void):m_count(0),wcid(0)
{
}
CSocketOverlappedCP::~CSocketOverlappedCP(void)
{
}
void CSocketOverlappedCP::doOverlapDataListen( SOCKET client )
{
m_overdata[m_count] = (LPPER_OVERLAPPEDCP_DATA)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,sizeof(PER_OVERLAPPEDCP_DATA));
m_overdata[m_count]->Buffer.buf = m_overdata[m_count]->buf;
m_overdata[m_count]->Buffer.len = BUFFERMAX;
m_overdata[m_count]->stClient = client;
m_overdata[m_count]->context = this;
WSARecv(client,&m_overdata[m_count]->Buffer,1,
&m_overdata[m_count]->dwNumOfBytesRecved,&m_overdata[m_count]->Flags,
&m_overdata[m_count]->overlap,CompletionCallBack);
m_count++;
}
int CSocketOverlappedCP::startServer()
{
if (initSocket())
{
socket_thread_create(&wcid,wait_client_thread,(void*)this);
return 1;
}
return -1;
}
int CSocketOverlappedCP::stopServer()
{
dispatchcallback(cbServerClose,NULL);
closesocket(m_listenSocket);
destroyedOverLappedData();
return 1;
}
bool CSocketOverlappedCP::sendtext( const std::string& content )
{
for (int i = 0;i < m_count; i++)
{
sendData(m_overdata[i]->stClient,content);
}
return true;
}
void CSocketOverlappedCP::destroyedOverLappedData()
{
for (int i = 0;i < m_count; i++)
{
destroyedOverLappedDataByIndex(i);
}
m_count = 0;
}
void CSocketOverlappedCP::destroyedOverLappedDataByIndex( int idx )
{
closesocket(m_overdata[idx]->stClient);
HeapFree(GetProcessHeap(),0,m_overdata[idx]);
}
void CSocketOverlappedCP::adjustOverlappedData( int idx )
{
if (idx < m_count - 1)
{
m_overdata[idx] = m_overdata[m_count - 1];
}
m_overdata[--m_count] = NULL;
}
void CSocketOverlappedCP::doOverlappedCallback( DWORD dwError,DWORD csTransferred, LPWSAOVERLAPPED lpOverlappped,DWORD dwFlags )
{
LPPER_OVERLAPPEDCP_DATA lperIOData=(LPPER_OVERLAPPEDCP_DATA)lpOverlappped;
DISPATCHPARAM dp;
memset(&dp,0,sizeof(DISPATCHPARAM));
if (dwError != 0 || csTransferred == 0)
{
int idx = getIndexBySocket(lperIOData->stClient);
if (idx != -1)
{
destroyedOverLappedDataByIndex(idx);
adjustOverlappedData(idx);
dispatchcallback(cbDisconnect,NULL);
}
}
else
{
strcpy(dp.msg,lperIOData->buf);
//回调到界面
dispatchcallback(cbCommunication,&dp);
//回调到接收完成
dispatchcallback(cbRecviced,NULL);
memset(&lperIOData->overlap,0,sizeof(WSAOVERLAPPED));
lperIOData->Buffer.len = BUFFERMAX;
lperIOData->Buffer.buf = lperIOData->buf;
WSARecv(lperIOData->stClient,&lperIOData->Buffer,1,
&lperIOData->dwNumOfBytesRecved,&lperIOData->Flags,
&lperIOData->overlap,CompletionCallBack);
}
}
int CSocketOverlappedCP::getIndexBySocket( SOCKET selclient )
{
int pos = -1;
for (int i = 0; i < m_count ;i++)
{
if (m_overdata[i]->stClient == selclient)
{
pos = i;
break;
}
}
return pos;
}
static void* wait_client_thread(void* param)
{
CSocketOverlappedCP *lapcp = (CSocketOverlappedCP*)param;
DISPATCHPARAM dp;
memset(&dp,0,sizeof(DISPATCHPARAM));
SOCKET socketClient;
while(true)
{
SOCKADDR_IN addrClient;
int addrClientSize=sizeof(SOCKADDR_IN);
socketClient=accept(lapcp->m_listenSocket,(struct sockaddr*)&addrClient,&addrClientSize);
if (socketClient==INVALID_SOCKET)
{
socketClient = NULL;
if (lapcp->checkSocketError(WSAGetLastError()))
{
break;
}
continue;
}
else
{
lapcp->doOverlapDataListen(socketClient);
strcpy(dp.info.ip,inet_ntoa(addrClient.sin_addr));
dp.info.port = addrClient.sin_port;
lapcp->dispatchcallback(cbHasConnect,&dp);
}
}
return 0;
}
//回到实例内部处理
void CALLBACK CompletionCallBack(DWORD dwError,DWORD csTransferred,
LPWSAOVERLAPPED lpOverlappped,DWORD dwFlags)
{
LPPER_OVERLAPPEDCP_DATA lperIOData=(LPPER_OVERLAPPEDCP_DATA)lpOverlappped;
CSocketOverlappedCP * overcp = NULL;
if (lperIOData->context != NULL)
{
overcp = (CSocketOverlappedCP*)lperIOData->context;
overcp->doOverlappedCallback(dwError,csTransferred,lpOverlappped,dwFlags);
}
}