1. 不使用线程池
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_)
//
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;
}
}
2. 暂时只封装了 win32 的 icop
3. 暂时还未写测试用例,因为不知道怎么写 -_-!!!