#include <WinSock2.h>
#include <MSTcpIP.h>
#include <Windows.h>
#include <process.h>
#include <set>
using namespace std;
#define I_PORT 1666
#define I_ADDR "0.0.0.0"
#define DFT_BUFFER_SIZE 4096
#define OPT_READ 0
#define OPT_WRITE 1
class CClient
{
public:
CClient()
{
}
~CClient()
{
}
SOCKET m_client;
DWORD m_tranSize;
char* m_buffer;
string m_ip;
};
class CPerData
{
public:
CPerData()
{
memset(&m_overlp,0,sizeof(WSAOVERLAPPED));
m_Buffer.buf = m_Buf;
m_Buffer.len = DFT_BUFFER_SIZE;
m_opt = -1;
}
~CPerData()
{
}
WSAOVERLAPPED m_overlp;
WSABUF m_Buffer;
int m_opt;
char m_Buf[DFT_BUFFER_SIZE];
};
class CIocp
{
public:
CIocp()
{
m_hIocp = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0,0);
m_sListen = WSASocket(AF_INET,SOCK_STREAM,0,0,0,WSA_FLAG_OVERLAPPED);
m_addr.sin_family = AF_INET;
m_addr.sin_port=htons(I_PORT);
m_addr.sin_addr.S_un.S_addr = inet_addr(I_ADDR);
int iret = bind(m_sListen,(sockaddr*)&m_addr, sizeof(sockaddr));
unsigned int tid;
m_hListen = (HANDLE)::_beginthreadex(0,0, CIocp::ListenProc,this, 0, &tid);
m_wsaEvent = ::WSACreateEvent();
::WSAEventSelect(m_sListen, m_wsaEvent, FD_ACCEPT|FD_CLOSE);
iret = ::listen(m_sListen,5);
SYSTEM_INFO sys;
::GetSystemInfo(&sys);
for (int i=0;i<sys.dwNumberOfProcessors;i++) //In fact, you should be create 2*number of cup +2 threads,here just test
{
m_hWork[i] = (HANDLE)::_beginthreadex(0,0, CIocp::ConProc,this, 0, &tid);
}
}
~CIocp()
{
}
private:
int InitListen()
{
int error = 0;
char _Name[100];
hostent * pHostEntry;
in_addr rAddr;
/* error = gethostname ( _Name, sizeof(_Name) );
if( 0 == error )
{
pHostEntry = gethostbyname( _Name );
if( pHostEntry != NULL )
{
memcpy( &rAddr, pHostEntry->h_addr_list[0], sizeof(struct in_addr) );
pm_HostIpAddress->assign( inet_ntoa( rAddr ) );
}
else
{
error = WSAGetLastError();
return error;
}
}
else
{
error = WSAGetLastError();
return error;
}
if(0 == error)
{
m_sListen=WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
if(m_sListen==INVALID_SOCKET)
{
error = WSAGetLastError();
return error;
}
}
*/
if(0 == error)
{
int r = 0;
int TimeOut=6000;
r = setsockopt(m_sListen,SOL_SOCKET,SO_SNDTIMEO,(char *)&TimeOut,sizeof(TimeOut));
int size;
size = 32768;
r = setsockopt(m_sListen,SOL_SOCKET,SO_RCVBUF,(const char *)&size,sizeof(int));
size = 32768;
r = setsockopt(m_sListen,SOL_SOCKET,SO_SNDBUF,(const char *)&size,sizeof(int));
int on = 1;
r = setsockopt(m_sListen, SOL_SOCKET, SO_KEEPALIVE,(const char *) &on, sizeof( int ) );
{
int iKeepAlive = -1;
int nOutSize = sizeof(int);
if (getsockopt(m_sListen, SOL_SOCKET, SO_KEEPALIVE, (char *)&iKeepAlive, &nOutSize) == SOCKET_ERROR)
{
}
else if (iKeepAlive == 1)
{
tcp_keepalive inKeepAlive;
memset(&inKeepAlive, 0, sizeof(tcp_keepalive));
unsigned long ulInLen = sizeof(tcp_keepalive);
tcp_keepalive outKeepAlive;
unsigned long ulOutLen = sizeof(tcp_keepalive);
unsigned long ulBytesReturn = 0;
inKeepAlive.onoff = 1;
inKeepAlive.keepaliveinterval = 60000;
inKeepAlive.keepalivetime = 3;
if (WSAIoctl(m_sListen, SIO_KEEPALIVE_VALS,
(LPVOID)&inKeepAlive, ulInLen,
(LPVOID)&outKeepAlive, ulOutLen,
&ulBytesReturn, NULL, NULL) == SOCKET_ERROR)
{
r = -1;
}
}
}
}
/* if(0==error)
{
sockaddr_in InternetAddr;
InternetAddr.sin_family=AF_INET;
InternetAddr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
InternetAddr.sin_port=htons(SvrPort);
if(bind(m_sListen,
(PSOCKADDR )&InternetAddr,
sizeof(InternetAddr))==SOCKET_ERROR)
{
error=GetLastError();
return error;
}
}
*/
}
void LisenWork()
{
while(::WSAWaitForMultipleEvents(1,&m_wsaEvent,TRUE,INFINITE,FALSE) != WAIT_FAILED)
{
::WSAResetEvent(m_wsaEvent);
WSANETWORKEVENTS nwEvnts ;
::WSAEnumNetworkEvents(m_sListen, m_wsaEvent, &nwEvnts);
if ((nwEvnts.lNetworkEvents & FD_ACCEPT) && (nwEvnts.iErrorCode[FD_ACCEPT_BIT] == 0))
{
int err = 0;
SOCKET s = ::WSAAccept(m_sListen,0,0,0,0);
CClient* client = new CClient;
client->m_client = s;
CPerData* pdata = new CPerData();
pdata->m_opt = 0;
m_client.insert(client);
SOCKADDR_IN addr = {0};
int asize = 0;
::getpeername(s, (SOCKADDR*)&addr,&asize);
client->m_ip = inet_ntoa(addr.sin_addr);
err = (int)::CreateIoCompletionPort((HANDLE)client->m_client, m_hIocp,(ULONG_PTR)client,0 );
DWORD flag=0; //must be set 0,or wsarecv return -1 and getlasterror is 10045
DWORD rsize = 0;
err = ::WSARecv(client->m_client,&pdata->m_Buffer,1,&rsize,&flag,&pdata->m_overlp,NULL);
err =::GetLastError();
int i = 0;
}
else if ((nwEvnts.lNetworkEvents & FD_CLOSE)&&(nwEvnts.iErrorCode[FD_CLOSE_BIT] == 0))
{
::closesocket(m_sListen);
return;
}
}
}
static unsigned int WINAPI ListenProc(void* proc)
{
CIocp* pThis = reinterpret_cast<CIocp*>(proc);
pThis->LisenWork();
return 0;
}
void RemoveClient(CClient* client)
{
::closesocket(client->m_client);
m_client.erase(m_client.find(client));
}
void ConWork()
{
while(true)
{
DWORD nSize = 0;
CClient* client = NULL;
CPerData* pdata=NULL;
int ret = ::GetQueuedCompletionStatus(m_hIocp, &nSize,(PULONG_PTR)&client, (LPOVERLAPPED*)&pdata, INFINITE);
if (ret != 0 )
{
if (nSize==0) //client closed
{
RemoveClient(client);
continue;
}
if (pdata->m_opt==OPT_READ)
{
//do something....
CPerData* psdata = pdata;
pdata->m_Buffer.len = nSize;
psdata->m_opt = OPT_WRITE;
DWORD tsize=0;
DWORD iflag=0;
memset(&psdata->m_overlp,0,sizeof(psdata->m_overlp));
int err = ::WSASend(client->m_client,&psdata->m_Buffer, 1, &tsize,iflag, (WSAOVERLAPPED*)psdata,0 );
err = ::GetLastError();
}
else if (pdata->m_opt==OPT_WRITE)
{
DWORD tsize=0;
DWORD iflag=0;
pdata->m_Buffer.len = DFT_BUFFER_SIZE;
memset(&pdata->m_overlp,0,sizeof(pdata->m_overlp));
pdata->m_opt = OPT_READ;
int err = ::WSARecv(client->m_client, &pdata->m_Buffer, 1, &tsize, &iflag, (WSAOVERLAPPED*)pdata,0);
err = ::GetLastError();
int i = 0;
}
}
else
{
RemoveClient(client);
continue;
}
}
}
static unsigned int WINAPI ConProc(void* proc)
{
CIocp* pThis = reinterpret_cast<CIocp*>(proc);
pThis->ConWork();
return 0;
}
private:
SOCKET m_sListen;
HANDLE m_hIocp;
SOCKADDR_IN m_addr;
HANDLE m_hListen;
HANDLE m_hWork[2];
WSAEVENT m_wsaEvent;
set<CClient*> m_client;
};
简单的iocp例子
最新推荐文章于 2024-02-18 21:19:30 发布