65,210
社区成员
发帖
与我相关
我的任务
分享
--------------------------
#include "cCompletePort.h"
int main(int _Argc, char **_argv)
{
WSADATA wsadt;
if(WSAStartup(MAKEWORD(2,2),&wsadt) != 0)
{
assert(0);
return -1;
}
cCompletePort test;
test.WaitThreadWork();
WSACleanup();
system("pause");
return 0;
}
typedef struct sPerHandleData
{
PERIODATA sPerIOData; //这样定义就只能进行一次IO操作,要等IO完成才能次下一次操作,最好独立出来
SOCKET sSvrSkt;
....
}
#include "cCompletePort.h"
#include "H:\CODE\common\net\net.h"
cCompletePort::cCompletePort(void)
{
mp_head = NULL;
m_hCompletionPort = NULL;
memset(m_hthread,0,sizeof(HANDLE) * MAX_THREAD_COUNT);
m_threadCount = 0;
m_perHandleDataSvrCount = 0;
if( !Init(PORT) )
{
printf("init() err.\n");
return;
}
}
cCompletePort::~cCompletePort(void)
{
if(m_hCompletionPort != NULL)
{
SAFE_CLOSEHANDLE(m_hCompletionPort);
}
for (int i = 0; i < m_threadCount; ++i)
{
SAFE_CLOSEHANDLE(m_hthread[i]);
}
PPERHANDLEDATA tmp_crt = mp_head,
tmp_nxt= mp_head;
do
{
tmp_nxt = tmp_nxt->next;
SAFE_CLODESOCKET(tmp_crt->sPerIOData.sCltSkt);
SAFE_CLODESOCKET(tmp_crt->sSvrSkt);
SAFE_DELETE(tmp_crt);
tmp_crt = tmp_nxt;
} while (tmp_crt != NULL);
tPerIOMapMap::iterator be = m_PerIOMapMap.begin();
PPERHANDLEDATA tmp_perHandleData = NULL;
while(be != m_PerIOMapMap.end())
{
tmp_perHandleData = (be++)->second;
if(tmp_perHandleData != NULL)
{
m_PerIOMapMap.erase(tmp_perHandleData->sPerIOData.sCltSkt);
SAFE_CLODESOCKET(tmp_perHandleData->sPerIOData.sCltSkt);
SAFE_DELETE(tmp_perHandleData);
}
}
m_PerIOMapMap.clear();
}
bool cCompletePort::Init( DWORD port, char *addr /*= NULL*/ )
{
int err = 0;
m_hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
if(m_hCompletionPort == NULL)
{
printf("CreateIoCompletionPort() err [%d].\n",err = WSAGetLastError());
assert(0);
return FALSE;
}
SYSTEM_INFO si;
GetSystemInfo(&si);
for (m_threadCount = 0; m_threadCount < 1/*si.dwNumberOfProcessors*//* * 2*/; ++m_threadCount)
{
m_hthread[m_threadCount] = (HANDLE)_beginthreadex(NULL,0,WorkThread,(PVOID)this,0,0);
if(m_hthread[m_threadCount] == NULL)
{
printf("_beginthreadex() err [%d].\n",GetLastError());
assert(0);
return false;
}
}
char szPort[5];
wsprintf(szPort,"%d",port);
struct addrinfo *res = ResolveAddress(AF_INET,SOCK_STREAM,IPPROTO_TCP,addr,szPort);
if(res == NULL)
{
printf("ResolveAddress() err.\n");
assert(0);
return false;
}
struct addrinfo *tmp_res = res;
while(tmp_res != NULL)
{
PPERHANDLEDATA tmp_svr = AllocPerHandleDataSvr();
if(tmp_svr == NULL)
{
assert(0);
return false;
}
tmp_svr->sAf = tmp_res->ai_family;
tmp_svr->sSockType = tmp_res->ai_socktype;
tmp_svr->sProtocol = tmp_res->ai_protocol;
tmp_svr->sSvrSkt = WSASocket(tmp_svr->sAf,tmp_svr->sSockType,tmp_svr->sProtocol,
0,0,WSA_FLAG_OVERLAPPED);
if(tmp_svr->sSvrSkt == INVALID_SOCKET)
{
printf("WSASocket() err [%d].\n",WSAGetLastError());
assert(0);
return false;
}
if( !Initlpfn( tmp_svr ) )
{
assert(0);
return false;
}
if(CreateIoCompletionPort((HANDLE)tmp_svr->sSvrSkt,
m_hCompletionPort,(ULONG_PTR)tmp_svr,0) == NULL)
{
printf("socket with CreateIoCompletionPort() err [%d].\n",WSAGetLastError());
assert(0);
return false;
}
memcpy( &tmp_svr->sPerIOData.sAddr,tmp_res->ai_addr,tmp_res->ai_addrlen);
tmp_svr->sPerIOData.sAddr_size = tmp_res->ai_addrlen;
err = bind(tmp_svr->sSvrSkt,(SOCKADDR*)&tmp_svr->sPerIOData.sAddr,
tmp_svr->sPerIOData.sAddr_size);
if(err == SOCKET_ERROR)
{
printf("bind() err [%d].\n",WSAGetLastError());
assert(0);
return false;
}
err = listen(tmp_svr->sSvrSkt,100);
if(err == SOCKET_ERROR)
{
printf("listen() err [%d].\n",WSAGetLastError());
assert(0);
return false;
}
if( !PostAcceptEx(tmp_svr) )
{
assert(0);
return false;
}
tmp_res = tmp_res->ai_next;
}
FreeAddrInfo(res);
return true;
}
bool cCompletePort::Initlpfn( PPERHANDLEDATA tmp_svr )
{
if(tmp_svr == NULL)
{
assert(0);
return false;
}
if(mp_head->next != NULL)
{
tmp_svr->slpfnAcceptEx = mp_head->next->slpfnAcceptEx;
tmp_svr->slpfnGetAcceptExSockaddrs = mp_head->next->slpfnGetAcceptExSockaddrs;
return true;
}
GUID guidAcceptEx = WSAID_ACCEPTEX;
DWORD bytes;
int rc = 0;
rc = WSAIoctl(
tmp_svr->sSvrSkt,
SIO_GET_EXTENSION_FUNCTION_POINTER,
&guidAcceptEx,
sizeof(guidAcceptEx),
&tmp_svr->slpfnAcceptEx,
sizeof(tmp_svr->slpfnAcceptEx),
&bytes,
NULL,
NULL
);
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "WSAIoctl: SIO_GET_EXTENSION_FUNCTION_POINTER failed: %d\n",
WSAGetLastError());
return false;
}
GUID guidGetAcceptExSockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
rc = WSAIoctl(
tmp_svr->sSvrSkt,
SIO_GET_EXTENSION_FUNCTION_POINTER,
&guidGetAcceptExSockaddrs,
sizeof(guidGetAcceptExSockaddrs),
&tmp_svr->slpfnGetAcceptExSockaddrs,
sizeof(tmp_svr->slpfnGetAcceptExSockaddrs),
&bytes,
NULL,
NULL
);
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "WSAIoctl: SIO_GET_EXTENSION_FUNCTION_POINTER faled: %d\n",
WSAGetLastError());
return false;
}
return true;
}
UINT WINAPI cCompletePort::WorkThread( PVOID lparam )
{
cCompletePort *pCp = (cCompletePort *)lparam;
pCp->BatchComplete();
return 0;
}
/***********************************************************************
作者: 王利
时间: 2012年5月6日21:18:09
修改时间: 2012年5月6日21:18:17
版本: 1.0
文件: cCompletePort.h
cCompletePort.cpp
H:\CODE\common\net\stdafx.h
H:\CODE\common\net\net.h
chat_svr.cpp
说明: 完成端口的示例代码
***********************************************************************/
#pragma once
#include "H:\CODE\common\net\stdafx.h"
const UINT MAX_THREAD_COUNT = 16;
#define QUIT_THREAD "quit"
enum eOperatorType
{
eOT_NONE = 0,
eOT_READ,
eOT_WRITE,
eOT_ACCEPT,
eOT_CLOSED,
eOT_END,
eOT_ERR,
eOT_MAX,
};
class cRAII_CriticalSection
{
public:
cRAII_CriticalSection(CRITICAL_SECTION *cs)
{
mp_cs = cs;
EnterCriticalSection(mp_cs);
}
~cRAII_CriticalSection()
{
LeaveCriticalSection(mp_cs);
}
private:
CRITICAL_SECTION *mp_cs;
};
typedef struct sPerIOData
{
WSAOVERLAPPED sOverlapped;
char sBuffer[BUFFER_SIZE];
DWORD sBuffer_size;
eOperatorType sOt;
SOCKET sCltSkt;
DWORD sAddr_size;
SOCKADDR_STORAGE sAddr;
CRITICAL_SECTION sSockCritSec;
}PERIODATA,*PPERIODATA;
typedef struct sPerHandleData
{
PERIODATA sPerIOData;
SOCKET sSvrSkt;
int sAf;
int sSockType;
int sProtocol;
LPFN_ACCEPTEX slpfnAcceptEx;
LPFN_GETACCEPTEXSOCKADDRS slpfnGetAcceptExSockaddrs;
struct sPerHandleData *next;
sPerHandleData(void)
{
slpfnAcceptEx = NULL;
slpfnGetAcceptExSockaddrs = NULL;
next = NULL;
}
}PERHANDLEDATA,*PPERHANDLEDATA;
class cCompletePort
{
public:
cCompletePort(void);
~cCompletePort(void);
public:
bool Init(DWORD port, char *addr = NULL);
void WaitThreadWork();
bool PostSend(PPERHANDLEDATA tmp_clt);
// 以下所有不是给你调用的,就是说 不是开放接口,不要在其他的类或者代码里使用以下所有
public:
void BatchComplete();
public:
static UINT WINAPI WorkThread(PVOID lparam);
private:
PPERHANDLEDATA AllocPerHandleDataSvr(void);
PPERHANDLEDATA AllocPerHandleDataClt(PPERHANDLEDATA tmp_svr);
bool ErasePerHandleData(SOCKET s);
bool Initlpfn(PPERHANDLEDATA tmp_svr);
bool PostAcceptEx(PPERHANDLEDATA tmp_svr);
bool AcceptComplete(PPERHANDLEDATA tmp_svr,PPERIODATA tmp_iodata);
bool PostRecv(PPERHANDLEDATA tmp_clt);
void PrintAcceptAddr(PPERHANDLEDATA tmp_clt);
void MsgDoPocessCenter(PPERIODATA tmp_iodata);
bool EndThread(PPERIODATA tmp_iodata);
bool SendComplete(PPERHANDLEDATA tmp_clt);
private:
PPERHANDLEDATA mp_head;
int m_perHandleDataSvrCount;
HANDLE m_hCompletionPort;
HANDLE m_hthread[MAX_THREAD_COUNT];
int m_threadCount;
typedef hash_map<SOCKET,PPERHANDLEDATA> tPerIOMapMap;
tPerIOMapMap m_PerIOMapMap;
};
#include "..\..\..\..\..\common\net\net.h"
int main(int argc, char **argv)
{
//if(argc <= 1)
//{
// printf("parameter is not enough.");
// return false;
//}
WSADATA wsadata = {0};
SOCKET SKT_send = 0;
SOCKADDR_IN SKD_addr;
int ret = 0;
if ((ret = WSAStartup(MAKEWORD(2,2), &wsadata)) != 0)
{
assert(0);
return false;
}
if((SKT_send = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == INVALID_SOCKET)
{
assert(0);
WSACleanup();
return false;
}
LookSvr(&SKD_addr);
SKD_addr.sin_port = htons(PORT);
char connect_count = 0;
const char connect_count_max = 3;
printf("连接中...\n");
while(connect_count < connect_count_max)
{
if(connect(SKT_send,(SOCKADDR *)&SKD_addr,sizeof(SKD_addr)) == SOCKET_ERROR)
{
++connect_count;
continue;
}
else
break;
}
if(connect_count < connect_count_max)
{
const unsigned int buffer_size = 2048;
char buffer[2048] = {0};
printf("连接成功,你可以输入数据...\n");
while(true)
{
cin.getline(buffer,buffer_size);
if(strlen(buffer) <= 0)
{
cin.clear();
buffer[0] = 0;
continue;
}
ret = send(SKT_send,buffer,buffer_size,0);
if(ret == SOCKET_ERROR)
{
printf("send err: %s\n",buffer);
assert(0);
}
memset(buffer,0,buffer_size);
ret = recv(SKT_send,buffer,buffer_size,0);
if(ret == SOCKET_ERROR)
{
printf("send err: %s\n",buffer);
assert(0);
}
else
{
printf("RECV:\t[%d]\t%s\n",strlen(buffer),buffer);
}
cin.clear();
buffer[0] = 0;
}
}
else
{
printf("连接超时,错误代码 [%d].\n",WSAGetLastError());
}
closesocket(SKT_send);
WSACleanup();
system("pause");
return 0;
}