1. 不使用线程池
2. 暂时只封装了 win32 的 icop
3. 暂时还未写测试用例,因为不知道怎么写 -_-!!!
2. 暂时只封装了 win32 的 icop
3. 暂时还未写测试用例,因为不知道怎么写 -_-!!!
//
networksocket.h: interface for the CNetworkSocket class.
//
/**/ //////////////////////////////////////////////////////////////////////
#if !defined(NETWORKSOCKET_H__A63ED8A5_7ED1_463D_A0F0_41F6E9C79441__INCLUDED_)
#define NETWORKSOCKET_H__A63ED8A5_7ED1_463D_A0F0_41F6E9C79441__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include < vector >
#include < winsock2.h >
#include < process.h >
#pragma comment(lib, " ws2_32.lib " )
#define BUFFER_SIZE 4096
enum OPERATION_TYPE
{
OPERATION_TYPE_RECV = 0,
OPERATION_TYPE_SEND = 1
} ;
// IO操作数据
typedef struct _PER_IO_OPERATION_DATA
{
OVERLAPPED OverLapped;
WSABUF DataBuf;
char szBuf[BUFFER_SIZE];
OPERATION_TYPE OperationType; // 操作类型表示
} PER_IO_OPERATION_DATA, * PPER_IO_OPERATION_DATA;
class CNetworkSocket
{
public:
CNetworkSocket();
virtual ~CNetworkSocket();
bool init();
bool uninit();
bool initNetWork(unsigned short nPort);
bool unitNetWork();
bool send(SOCKET s, const char* pBuf, int nLen);
private:
SOCKET m_listensock;
HANDLE m_hIocpPort;
std::vector<HANDLE> m_vectorThreadHandle;
static unsigned __stdcall _WorkerThreadProc(void* pVoid);
static unsigned __stdcall _AcceptThreadProc(void* pVoid);
} ;
#endif // !defined(NETWORKSOCKET_H__A63ED8A5_7ED1_463D_A0F0_41F6E9C79441__INCLUDED_)
//
/**/ //////////////////////////////////////////////////////////////////////
#if !defined(NETWORKSOCKET_H__A63ED8A5_7ED1_463D_A0F0_41F6E9C79441__INCLUDED_)
#define NETWORKSOCKET_H__A63ED8A5_7ED1_463D_A0F0_41F6E9C79441__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include < vector >
#include < winsock2.h >
#include < process.h >
#pragma comment(lib, " ws2_32.lib " )
#define BUFFER_SIZE 4096
enum OPERATION_TYPE
{
OPERATION_TYPE_RECV = 0,
OPERATION_TYPE_SEND = 1
} ;
// IO操作数据
typedef struct _PER_IO_OPERATION_DATA
{
OVERLAPPED OverLapped;
WSABUF DataBuf;
char szBuf[BUFFER_SIZE];
OPERATION_TYPE OperationType; // 操作类型表示
} PER_IO_OPERATION_DATA, * PPER_IO_OPERATION_DATA;
class CNetworkSocket
{
public:
CNetworkSocket();
virtual ~CNetworkSocket();
bool init();
bool uninit();
bool initNetWork(unsigned short nPort);
bool unitNetWork();
bool send(SOCKET s, const char* pBuf, int nLen);
private:
SOCKET m_listensock;
HANDLE m_hIocpPort;
std::vector<HANDLE> m_vectorThreadHandle;
static unsigned __stdcall _WorkerThreadProc(void* pVoid);
static unsigned __stdcall _AcceptThreadProc(void* pVoid);
} ;
#endif // !defined(NETWORKSOCKET_H__A63ED8A5_7ED1_463D_A0F0_41F6E9C79441__INCLUDED_)
//
networksocket.cpp: implementation of the CNetworkSocket class.
//
/**/ //////////////////////////////////////////////////////////////////////
#include " networksocket.h "
/**/ //////////////////////////////////////////////////////////////////////
// Construction/Destruction
/**/ //////////////////////////////////////////////////////////////////////
CNetworkSocket::CNetworkSocket()
{
m_listensock = INVALID_SOCKET;
m_hIocpPort = INVALID_HANDLE_VALUE;
}
CNetworkSocket:: ~ CNetworkSocket()
{
}
bool CNetworkSocket::init()
{
WORD wVersionRequested;
WSADATA wsaData;
int nErrCode = 0;
wVersionRequested = MAKEWORD(2, 2);
nErrCode = ::WSAStartup(wVersionRequested, &wsaData);
if ( nErrCode != 0 )
{
return false;
}
if ( LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2 )
{
bool b = uninit();
return false;
}
else
{
return true;
}
}
bool CNetworkSocket::uninit()
{
int nErrCode = 0;
nErrCode = ::WSACleanup();
return true;
}
bool CNetworkSocket::initNetWork(unsigned short nPort)
{
int nErrCode = 0;
// 创建 socket
m_listensock = ::WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
if( INVALID_SOCKET == m_listensock )
{
nErrCode = ::WSAGetLastError();
return false;
}
// 绑定端口
sockaddr_in InternetAddr;
InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.S_un.S_addr = ::htonl(INADDR_ANY);
InternetAddr.sin_port = htons(nPort);
if( ::bind( m_listensock, (PSOCKADDR)&InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR )
{
nErrCode = ::WSAGetLastError();
return false;
}
// 开始监听
if( ::listen(m_listensock, 5) == SOCKET_ERROR )
{
nErrCode = ::WSAGetLastError();
return false;
}
// 创建完成端口
m_hIocpPort = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
if( m_hIocpPort == INVALID_HANDLE_VALUE )
{
nErrCode = ::WSAGetLastError();
return false;
}
// 启动工作线程,线程数为CPU处理器数量*2+2
SYSTEM_INFO sys_Info;
::GetSystemInfo(&sys_Info);
for(int i = 0; i < (int(sys_Info.dwNumberOfProcessors) * 2 + 2); i++)
{
HANDLE ThreadHandle = INVALID_HANDLE_VALUE;
DWORD ThreadID = 0;
unsigned int nThreadId = 0 ;
ThreadHandle = (HANDLE)_beginthreadex(NULL, 0, _WorkerThreadProc, (void *)this, 0, &nThreadId);
if ( ThreadHandle == 0 )
return false;
m_vectorThreadHandle.push_back(ThreadHandle);
}
// 启动侦听线程
HANDLE ThreadHandle = INVALID_HANDLE_VALUE;
unsigned int nThreadId = 0 ;
ThreadHandle = (HANDLE)_beginthreadex(NULL, 0, _AcceptThreadProc, (void *)this, 0, &nThreadId);
if ( ThreadHandle == 0 )
return false;
m_vectorThreadHandle.push_back(ThreadHandle);
return true;
}
bool CNetworkSocket::unitNetWork()
{
// 启动工作线程,线程数为CPU处理器数量*2+2
SYSTEM_INFO sys_Info;
::GetSystemInfo(&sys_Info);
for(int i = 0; i < (int(sys_Info.dwNumberOfProcessors) * 2 + 2); i++)
{
//寄出退出消息
::PostQueuedCompletionStatus(m_hIocpPort, -1, -1, NULL);
}
std::vector<HANDLE>::iterator iter_t;
for ( iter_t = m_vectorThreadHandle.begin(); iter_t != m_vectorThreadHandle.end(); iter_t++ )
{
DWORD dwRet = ::WaitForSingleObject(*iter_t, INFINITE);
}
//关闭网络的侦听
::shutdown(m_listensock, 0);
::closesocket(m_listensock);
return true;
}
unsigned __stdcall CNetworkSocket::_WorkerThreadProc( void * pVoid)
{
CNetworkSocket* pThis = (CNetworkSocket*)pVoid;
DWORD dwByteTransferred = 0;
unsigned long nFlag = 0;
DWORD RecvByte = 0;
SOCKET ClientSock = INVALID_SOCKET;
PPER_IO_OPERATION_DATA PerIoData;
while ( true )
{
BOOL bSuccess = ::GetQueuedCompletionStatus(pThis->m_hIocpPort,
&dwByteTransferred,
(LPDWORD)&ClientSock,
(LPOVERLAPPED*)&PerIoData,
INFINITE);
//退出信号到达,退出线程
if( dwByteTransferred == -1 && PerIoData == NULL )
return 1;
//客户机已经断开连接或者连接出现错误
if( dwByteTransferred == 0 && (PerIoData->OperationType == OPERATION_TYPE_RECV || PerIoData->OperationType == OPERATION_TYPE_SEND ) )
{
::closesocket(ClientSock);
::GlobalFree(PerIoData);
continue;
}
// 接收完成
if ( PerIoData->OperationType == OPERATION_TYPE_RECV )
{
// 处理接收数据
// pThis->OnRecv(ClientSock, PerIoData->szBuf, dwByteTransferred);
//将源数据置空
::memset(PerIoData->szBuf, 0, BUFFER_SIZE);
dwByteTransferred=0;
//重置IO操作数据
unsigned long Flag=0;
::ZeroMemory(&(PerIoData->OverLapped), sizeof(OVERLAPPED));
PerIoData->DataBuf.buf = PerIoData->szBuf;
PerIoData->DataBuf.len = BUFFER_SIZE;
PerIoData->OperationType = OPERATION_TYPE_RECV;
// 再投递另一个Recv请求
::WSARecv(ClientSock, &(PerIoData->DataBuf), 1, &RecvByte, &Flag, &(PerIoData->OverLapped), NULL);
}
// 发送完成,置空缓冲区,释放缓冲区
if( PerIoData->OperationType == OPERATION_TYPE_SEND )
{
::memset(PerIoData, 0, sizeof(PER_IO_OPERATION_DATA));
::GlobalFree(PerIoData);
dwByteTransferred = 0;
}
}// while ( true )
return 0;
}
unsigned __stdcall CNetworkSocket::_AcceptThreadProc( void * pVoid)
{
CNetworkSocket* pThis = (CNetworkSocket*)pVoid;
SOCKET AcceptSock = INVALID_SOCKET;
while ( true )
{
AcceptSock = ::WSAAccept(pThis->m_listensock, NULL, NULL, NULL, 0);
//关联客户端口到完成端口,句柄数据在此时被绑定到完成端口
::CreateIoCompletionPort((HANDLE)AcceptSock, pThis->m_hIocpPort, (DWORD)AcceptSock, 0);
PPER_IO_OPERATION_DATA PerIoData = (PPER_IO_OPERATION_DATA)::GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA));
unsigned long nFlag = 0;
DWORD RecvByte = 0;
::ZeroMemory(&(PerIoData->OverLapped),sizeof(OVERLAPPED));
PerIoData->DataBuf.buf = PerIoData->szBuf;
PerIoData->DataBuf.len = BUFFER_SIZE;
PerIoData->OperationType = OPERATION_TYPE_RECV;
//提交首个接收数据请求
//这时
//如果客户端断开连接
//则也可以以接收数据时得到通知
::WSARecv(AcceptSock, &(PerIoData->DataBuf), 1, &RecvByte, &nFlag, &(PerIoData->OverLapped), NULL);
}// while ( true )
return 0;
}
bool CNetworkSocket::send(SOCKET s, const char * pBuf, int nLen)
{
if( s == INVALID_SOCKET || pBuf == NULL || nLen == 0 )
return false;
PPER_IO_OPERATION_DATA PerIoData = (PPER_IO_OPERATION_DATA)::GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA));
unsigned long nFlag = 0;
DWORD dwSendByte = 0;
::ZeroMemory(&(PerIoData->OverLapped), sizeof(OVERLAPPED));
::memcpy(PerIoData->szBuf, pBuf, nLen);
PerIoData->DataBuf.buf = PerIoData->szBuf;
PerIoData->DataBuf.len = nLen;
PerIoData->OperationType = OPERATION_TYPE_SEND;
int nRet = ::WSASend(s, &(PerIoData->DataBuf), 1, &dwSendByte, nFlag, &(PerIoData->OverLapped), NULL);
if( nRet==SOCKET_ERROR && GetLastError() != WSA_IO_PENDING )
{
return false;
}
else
{
return true;
}
}
//
/**/ //////////////////////////////////////////////////////////////////////
#include " networksocket.h "
/**/ //////////////////////////////////////////////////////////////////////
// Construction/Destruction
/**/ //////////////////////////////////////////////////////////////////////
CNetworkSocket::CNetworkSocket()
{
m_listensock = INVALID_SOCKET;
m_hIocpPort = INVALID_HANDLE_VALUE;
}
CNetworkSocket:: ~ CNetworkSocket()
{
}
bool CNetworkSocket::init()
{
WORD wVersionRequested;
WSADATA wsaData;
int nErrCode = 0;
wVersionRequested = MAKEWORD(2, 2);
nErrCode = ::WSAStartup(wVersionRequested, &wsaData);
if ( nErrCode != 0 )
{
return false;
}
if ( LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2 )
{
bool b = uninit();
return false;
}
else
{
return true;
}
}
bool CNetworkSocket::uninit()
{
int nErrCode = 0;
nErrCode = ::WSACleanup();
return true;
}
bool CNetworkSocket::initNetWork(unsigned short nPort)
{
int nErrCode = 0;
// 创建 socket
m_listensock = ::WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
if( INVALID_SOCKET == m_listensock )
{
nErrCode = ::WSAGetLastError();
return false;
}
// 绑定端口
sockaddr_in InternetAddr;
InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.S_un.S_addr = ::htonl(INADDR_ANY);
InternetAddr.sin_port = htons(nPort);
if( ::bind( m_listensock, (PSOCKADDR)&InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR )
{
nErrCode = ::WSAGetLastError();
return false;
}
// 开始监听
if( ::listen(m_listensock, 5) == SOCKET_ERROR )
{
nErrCode = ::WSAGetLastError();
return false;
}
// 创建完成端口
m_hIocpPort = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
if( m_hIocpPort == INVALID_HANDLE_VALUE )
{
nErrCode = ::WSAGetLastError();
return false;
}
// 启动工作线程,线程数为CPU处理器数量*2+2
SYSTEM_INFO sys_Info;
::GetSystemInfo(&sys_Info);
for(int i = 0; i < (int(sys_Info.dwNumberOfProcessors) * 2 + 2); i++)
{
HANDLE ThreadHandle = INVALID_HANDLE_VALUE;
DWORD ThreadID = 0;
unsigned int nThreadId = 0 ;
ThreadHandle = (HANDLE)_beginthreadex(NULL, 0, _WorkerThreadProc, (void *)this, 0, &nThreadId);
if ( ThreadHandle == 0 )
return false;
m_vectorThreadHandle.push_back(ThreadHandle);
}
// 启动侦听线程
HANDLE ThreadHandle = INVALID_HANDLE_VALUE;
unsigned int nThreadId = 0 ;
ThreadHandle = (HANDLE)_beginthreadex(NULL, 0, _AcceptThreadProc, (void *)this, 0, &nThreadId);
if ( ThreadHandle == 0 )
return false;
m_vectorThreadHandle.push_back(ThreadHandle);
return true;
}
bool CNetworkSocket::unitNetWork()
{
// 启动工作线程,线程数为CPU处理器数量*2+2
SYSTEM_INFO sys_Info;
::GetSystemInfo(&sys_Info);
for(int i = 0; i < (int(sys_Info.dwNumberOfProcessors) * 2 + 2); i++)
{
//寄出退出消息
::PostQueuedCompletionStatus(m_hIocpPort, -1, -1, NULL);
}
std::vector<HANDLE>::iterator iter_t;
for ( iter_t = m_vectorThreadHandle.begin(); iter_t != m_vectorThreadHandle.end(); iter_t++ )
{
DWORD dwRet = ::WaitForSingleObject(*iter_t, INFINITE);
}
//关闭网络的侦听
::shutdown(m_listensock, 0);
::closesocket(m_listensock);
return true;
}
unsigned __stdcall CNetworkSocket::_WorkerThreadProc( void * pVoid)
{
CNetworkSocket* pThis = (CNetworkSocket*)pVoid;
DWORD dwByteTransferred = 0;
unsigned long nFlag = 0;
DWORD RecvByte = 0;
SOCKET ClientSock = INVALID_SOCKET;
PPER_IO_OPERATION_DATA PerIoData;
while ( true )
{
BOOL bSuccess = ::GetQueuedCompletionStatus(pThis->m_hIocpPort,
&dwByteTransferred,
(LPDWORD)&ClientSock,
(LPOVERLAPPED*)&PerIoData,
INFINITE);
//退出信号到达,退出线程
if( dwByteTransferred == -1 && PerIoData == NULL )
return 1;
//客户机已经断开连接或者连接出现错误
if( dwByteTransferred == 0 && (PerIoData->OperationType == OPERATION_TYPE_RECV || PerIoData->OperationType == OPERATION_TYPE_SEND ) )
{
::closesocket(ClientSock);
::GlobalFree(PerIoData);
continue;
}
// 接收完成
if ( PerIoData->OperationType == OPERATION_TYPE_RECV )
{
// 处理接收数据
// pThis->OnRecv(ClientSock, PerIoData->szBuf, dwByteTransferred);
//将源数据置空
::memset(PerIoData->szBuf, 0, BUFFER_SIZE);
dwByteTransferred=0;
//重置IO操作数据
unsigned long Flag=0;
::ZeroMemory(&(PerIoData->OverLapped), sizeof(OVERLAPPED));
PerIoData->DataBuf.buf = PerIoData->szBuf;
PerIoData->DataBuf.len = BUFFER_SIZE;
PerIoData->OperationType = OPERATION_TYPE_RECV;
// 再投递另一个Recv请求
::WSARecv(ClientSock, &(PerIoData->DataBuf), 1, &RecvByte, &Flag, &(PerIoData->OverLapped), NULL);
}
// 发送完成,置空缓冲区,释放缓冲区
if( PerIoData->OperationType == OPERATION_TYPE_SEND )
{
::memset(PerIoData, 0, sizeof(PER_IO_OPERATION_DATA));
::GlobalFree(PerIoData);
dwByteTransferred = 0;
}
}// while ( true )
return 0;
}
unsigned __stdcall CNetworkSocket::_AcceptThreadProc( void * pVoid)
{
CNetworkSocket* pThis = (CNetworkSocket*)pVoid;
SOCKET AcceptSock = INVALID_SOCKET;
while ( true )
{
AcceptSock = ::WSAAccept(pThis->m_listensock, NULL, NULL, NULL, 0);
//关联客户端口到完成端口,句柄数据在此时被绑定到完成端口
::CreateIoCompletionPort((HANDLE)AcceptSock, pThis->m_hIocpPort, (DWORD)AcceptSock, 0);
PPER_IO_OPERATION_DATA PerIoData = (PPER_IO_OPERATION_DATA)::GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA));
unsigned long nFlag = 0;
DWORD RecvByte = 0;
::ZeroMemory(&(PerIoData->OverLapped),sizeof(OVERLAPPED));
PerIoData->DataBuf.buf = PerIoData->szBuf;
PerIoData->DataBuf.len = BUFFER_SIZE;
PerIoData->OperationType = OPERATION_TYPE_RECV;
//提交首个接收数据请求
//这时
//如果客户端断开连接
//则也可以以接收数据时得到通知
::WSARecv(AcceptSock, &(PerIoData->DataBuf), 1, &RecvByte, &nFlag, &(PerIoData->OverLapped), NULL);
}// while ( true )
return 0;
}
bool CNetworkSocket::send(SOCKET s, const char * pBuf, int nLen)
{
if( s == INVALID_SOCKET || pBuf == NULL || nLen == 0 )
return false;
PPER_IO_OPERATION_DATA PerIoData = (PPER_IO_OPERATION_DATA)::GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA));
unsigned long nFlag = 0;
DWORD dwSendByte = 0;
::ZeroMemory(&(PerIoData->OverLapped), sizeof(OVERLAPPED));
::memcpy(PerIoData->szBuf, pBuf, nLen);
PerIoData->DataBuf.buf = PerIoData->szBuf;
PerIoData->DataBuf.len = nLen;
PerIoData->OperationType = OPERATION_TYPE_SEND;
int nRet = ::WSASend(s, &(PerIoData->DataBuf), 1, &dwSendByte, nFlag, &(PerIoData->OverLapped), NULL);
if( nRet==SOCKET_ERROR && GetLastError() != WSA_IO_PENDING )
{
return false;
}
else
{
return true;
}
}