=-------------------------socketpool.h
#pragma once
#include "Const.h"
#include <list>
#include "dll.h"
//
// 客户端连接池
// 在客户端连接前,先建立socket,在连接时,可以加快响应速度。
// 在高并发的情况下,可以提高访问量
//
class IOCP_API CClientSocketPool
{
public:
CClientSocketPool(void);
virtual ~CClientSocketPool(void);
public:
//初始化连接池
int Initialize(int count, SOCKET listenSock, HANDLE hCompletePort);
//增加TCP监听缓冲区
int AddTCPAcceptBuff( int count);
//初始UDP连接池
int InitUDPSocket(SOCKET listenSock, HANDLE hCompletePort, int count = 1);
//关闭连接池
int Close(void);
//释放连接
int ReleaseClientSock(ClientSocket* pClientSock);
int GetTcpClientSock(std::list<ClientSocket*>& clientSocketList)
{
clientSocketList.clear();
EnterCriticalSection(&cs);
clientSocketList = m_clientSocketList;
LeaveCriticalSection(&cs);
return 0;
}
private:
//设置socket参数
int SettingClientSocket(ClientSocket* pClientSocket);
private:
int m_iSocketCount;
SOCKET m_listenSock;
HANDLE hCompletePort;
LPFN_ACCEPTEX m_lpfnAcceptEx;
CRITICAL_SECTION cs;
std::list<ClientSocket*> m_clientSocketList; //tcp连接池
std::list<ClientSocket*> m_UDPSocketList; //udp连接池
};
---------------------socketpool.cpp
#include "SocketPool.h"
CClientSocketPool::CClientSocketPool(void)
{
InitializeCriticalSection(&cs);
m_lpfnAcceptEx = NULL;//2008-9-9 modify by meng junshen
}
CClientSocketPool::~CClientSocketPool(void)
{
//释放所有创建的ClientSock
Close();
DeleteCriticalSection(&cs);
}
int CClientSocketPool::Initialize( int count, SOCKET listenSock, HANDLE hCompletePort )
{
this->m_listenSock = listenSock;
this->hCompletePort = hCompletePort;
//获取AcceptEx函数指针
GUID wsaidAcceptEx = WSAID_ACCEPTEX;
DWORD dwBytes = 0;
WSAIoctl(listenSock,
SIO_GET_EXTENSION_FUNCTION_POINTER,
&wsaidAcceptEx,
sizeof(wsaidAcceptEx),
&m_lpfnAcceptEx,
sizeof(m_lpfnAcceptEx),
&dwBytes,
NULL,
NULL);
//创建指定数量的Socket
for(int i=0; i < count; i++)
{
ClientSocket* pClientSock = new ClientSocket();
pClientSock->bIsServer = true;
pClientSock->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SettingClientSocket(pClientSock);
m_clientSocketList.push_back(pClientSock);
}
return 0;
}
//释放所有创建的ClientSock
int CClientSocketPool::Close(void)
{
ClientSocket* pClientSock = NULL;
EnterCriticalSection(&cs);
//关闭所有的连接
std::list<ClientSocket*>::iterator itr = m_clientSocketList.begin();
for (; itr != m_clientSocketList.end(); ++itr)
{
pClientSock = *itr;
LINGER linger;
linger.l_onoff = 1;
linger.l_linger = 0;
setsockopt( pClientSock->socket, SOL_SOCKET, SO_LINGER, (char *)&linger, sizeof(linger) );
CancelIo((HANDLE) pClientSock->socket);
closesocket(pClientSock->socket);
Sleep(1);
delete pClientSock;
pClientSock = NULL;
}
//析放所有udp连接资源
itr = m_UDPSocketList.begin();
for (; itr != m_UDPSocketList.end(); ++itr)
{ if (*itr) //关闭socket
{
closesocket((*itr)->socket);
}
delete *itr;
*itr = NULL;
}
m_UDPSocketList.clear();
m_clientSocketList.clear();
LeaveCriticalSection(&cs);
return 0;
}
//释放ClientSocket,将重新创建一个Socket加入到等待列表
int CClientSocketPool::ReleaseClientSock( ClientSocket* pClientSock )
{
if( pClientSock )
{
LINGER linger;
linger.l_onoff = 1;
linger.l_linger = 0;
setsockopt( pClientSock->socket, SOL_SOCKET, SO_LINGER, (char *)&linger, sizeof(linger) );
CancelIo((HANDLE) pClientSock->socket);
shutdown(pClientSock->socket, 1000);
//closesocket(pClientSock->socket);
//pClientSock->bIsServer = FALSE;//2008-9-9 modify by meng junshen
pClientSock->socket = INVALID_SOCKET;
if (pClientSock->bIsServer)
{
//重新创建一个Socket来等待
pClientSock->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SettingClientSocket(pClientSock);
}
}
return 0;
}
//设置Socket参数,异步等待Socket连接,并关联完成端口
int CClientSocketPool::SettingClientSocket( ClientSocket* pClientSock )
{
if ( pClientSock )
{
SOCKET socket = pClientSock->socket;
//异步等待Socket连接
memset( &(pClientSock->olex) , 0, sizeof(OVERLAPPEDEX));
pClientSock->bIsUPDSock = FALSE; //设置UDP连接标志
pClientSock->olex.pClientSock = pClientSock;
pClientSock->olex.ioType = ACCEPT;
pClientSock->olex.wsabuf.buf = pClientSock->olex.buf;
pClientSock->bytesTransferred = 0;
if (m_lpfnAcceptEx != NULL)//2008-9-9 modify by meng junshen
{
DWORD ret = m_lpfnAcceptEx(m_listenSock,
socket,
pClientSock->AddressBuffer,
0,
SOCKADDR_IN_SIZE,
SOCKADDR_IN_SIZE,
&(pClientSock->bytesTransferred),
(LPOVERLAPPED)&(pClientSock->olex));
//关联完成端口
CreateIoCompletionPort((HANDLE)socket,hCompletePort,(DWORD)pClientSock,0);
}
}
return 0;
}
/***********************************************************************************************************/
//Function: InitUDPSocket
//Notes: 初始化完成端口UDP连接,投递udp数据接受
//
//Input: ClientSocket* listenSock用户的连接信息
// HANDLE hCompletePort完成端口句柄
// count 读取数据投递数量
/***********************************************************************************************************/
int CClientSocketPool::InitUDPSocket( SOCKET listenSock, HANDLE hCompletePort, int count)
{
int res = 0;
ClientSocket* pClientSock = new ClientSocket();
if ( pClientSock )
{
pClientSock->socket = listenSock;
SOCKET socket = pClientSock->socket;
//关联完成端口
CreateIoCompletionPort((HANDLE)listenSock, hCompletePort,(DWORD)pClientSock, 0);
m_UDPSocketList.push_back(pClientSock);
//准备接受数据包
for (int i =0; i < 4; ++i)
{
if (NULL == pClientSock)
{
pClientSock = new ClientSocket();
pClientSock->socket = listenSock;
m_UDPSocketList.push_back(pClientSock);
}
//异步等待Socket连接
memset( &(pClientSock->olex) , 0, sizeof(OVERLAPPEDEX));
pClientSock->olex.pClientSock = pClientSock;
pClientSock->olex.wsabuf.buf = pClientSock->olex.buf;
pClientSock->bytesTransferred = 0;
pClientSock->bIsUPDSock = TRUE; //设置UDP连接标志
pClientSock->iAddrLen = sizeof(sockaddr_in);
DWORD flag = MSG_PARTIAL;
DWORD ioSize = 0;
pClientSock->olex.ioType = READ;
pClientSock->olex.wsabuf.len = DATA_BUF_LENGHT;
int rtSend = WSARecvFrom(
pClientSock->socket,
&pClientSock->olex.wsabuf,
1,
&pClientSock->bytesTransferred,
&flag,
(sockaddr*)pClientSock->AddressBuffer,
&pClientSock->iAddrLen,
(LPOVERLAPPED)&pClientSock->olex,
0);
res = GetLastError();
if ( SOCKET_ERROR == rtSend &&
WSA_IO_PENDING != GetLastError())
{
closesocket(listenSock);
}
pClientSock = NULL;
}
}
return 0;
}
/***********************************************************************************************************/
//Function: AddTCPAcceptBuff
//Notes: 增加TCP监听缓冲区
//
//Input: count需要添加的接收连接缓冲区数量
/***********************************************************************************************************/
int CClientSocketPool::AddTCPAcceptBuff(int count)
{
//获取AcceptEx函数指针
if (NULL == m_lpfnAcceptEx)
{
GUID wsaidAcceptEx = WSAID_ACCEPTEX;
DWORD dwBytes = 0;
WSAIoctl(m_listenSock,
SIO_GET_EXTENSION_FUNCTION_POINTER,
&wsaidAcceptEx,
sizeof(wsaidAcceptEx),
&m_lpfnAcceptEx,
sizeof(m_lpfnAcceptEx),
&dwBytes,
NULL,
NULL);
}
//创建指定数量的Socket
for(int i=0; i < count; i++)
{
ClientSocket* pClientSock = new ClientSocket();
pClientSock->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SettingClientSocket(pClientSock);
m_clientSocketList.push_back(pClientSock);
}
return 0;
}