C++ IOCP windows服务器
作者:网络转载 发布时间:[ 2014/9/3 11:42:19 ] 推荐标签:C++ NET 服务器
/*******************
处理消息类
*******************/
void CMYIOCPServer::HandleMessage()
{
printf("thread is %d ",GetCurrentThreadId());
WorkItemBase *pCworkItem = NULL;
byte iCommand = m_byteMsg[0];
switch(iCommand)
{
case '0':
pCworkItem = new CWorkA();
break;
case '1':
pCworkItem = new CWorkB();
break;
case '2':
break;
default:
break;
}
//将任务交给线程池处理
if(NULL != pCworkItem)
{
m_CWorkQueue.InsertWorkItem(pCworkItem);
}
printf("Finish Handle Message ");
}
/**************************
发送消息给制定客户端
**************************/
void CMYIOCPServer::SendMessage(SOCKET &tSOCKET,char MessAge[MessMaxLen])
{
// 开始数据处理,接收来自客户端的数据
WaitForSingleObject(m_hMutex,INFINITE);
send(tSOCKET, MessAge, MessMaxLen, 0); // 发送信息
ReleaseMutex(m_hMutex);
}
/**************************
初始化SOCKET对象,创建端口
和线程数组
**************************/
bool CMYIOCPServer::LoadWindowsSocket()
{
// 加载socket动态链接库
WORD wVersionRequested = MAKEWORD(2, 2); // 请求2.2版本的WinSock库
WSADATA wsaData; // 接收Windows Socket的结构信息
DWORD err = WSAStartup(wVersionRequested, &wsaData);
if (0 != err){ // 检查套接字库是否申请成功
m_sError = "Request Windows Socket Library Error! ";
return false;
}
if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){// 检查是否申请了所需版本的套接字库
WSACleanup();
m_sError ="Request Windows Socket Version 2.2 Error! ";
system("pause");
return false;
}
// 创建IOCP的内核对象
/**
* 需要用到的函数的原型:
* HANDLE WINAPI CreateIoCompletionPort(
* __in HANDLE FileHandle, // 已经打开的文件句柄或者空句柄,一般是客户端的句柄
* __in HANDLE ExistingCompletionPort, // 已经存在的IOCP句柄
* __in ULONG_PTR CompletionKey, // 完成键,包含了指定I/O完成包的指定文件
* __in DWORD NumberOfConcurrentThreads // 真正并发同时执行大线程数,一般推介是CPU核心数*2
* );
**/
m_completionPort = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 0);
if (NULL == m_completionPort){ // 创建IO内核对象失败
m_sError ="CreateIoCompletionPort failed. Error: ";
return false;
}
// 创建IOCP线程--线程里面创建线程池
// 确定处理器的核心数量
SYSTEM_INFO mySysInfo;
GetSystemInfo(&mySysInfo);
// 基于处理器的核心数量创建线程
for(DWORD i = 0; i < (mySysInfo.dwNumberOfProcessors * 2); ++i){
// 创建服务器工作器线程,并将完成端口传递到该线程
HANDLE ThreadHandle = CreateThread(NULL, 0, &CMYIOCPServer::ServerWorkThread, m_completionPort, 0, NULL);
if(NULL == ThreadHandle){
m_sError ="Create Thread Handle failed. Error:: ";
}
CloseHandle(ThreadHandle);
}
return true;
}
/*************************
初始化服务器SOCKET信息
*************************/
bool CMYIOCPServer::InitServerSocket()
{
// 建立流式套接字
m_srvSocket = socket(AF_INET, SOCK_STREAM, 0);
// 绑定SOCKET到本机
SOCKADDR_IN srvAddr;
srvAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
srvAddr.sin_family = AF_INET;
srvAddr.sin_port = htons(m_iLisenPoint);
int bindResult = bind(m_srvSocket, (SOCKADDR*)&srvAddr, sizeof(SOCKADDR));
if(SOCKET_ERROR == bindResult){
m_sError = "Bind failed. Error:";
return false;
}
return true;
}
/**************************
创建服务器端的监听信息
**************************/
bool CMYIOCPServer::CreateServerSocker()
{
// 将SOCKET设置为监听模式
int listenResult = listen(m_srvSocket, 10);
if(SOCKET_ERROR == listenResult){
m_sError = "Listen failed. Error: " ;
return false;
}
// 开始处理IO数据
cout << "本服务器已准备绪,正在等待客户端的接入... ";
int icount = 0;
while(true){
PER_HANDLE_DATA * PerHandleData = NULL;
SOCKADDR_IN saRemote;
int RemoteLen;
SOCKET acceptSocket;
// 接收连接,并分配完成端,这儿可以用AcceptEx()
RemoteLen = sizeof(saRemote);
acceptSocket = accept(m_srvSocket, (SOCKADDR*)&saRemote, &RemoteLen);
if(SOCKET_ERROR == acceptSocket){ // 接收客户端失败
cerr << "Accept Socket Error: " << GetLastError() << endl;
m_sError = "Accept Socket Error: " ;
icount++;
if(icount > 50)
{
return false;
}
continue;
}
icount = 0;
// 创建用来和套接字关联的单句柄数据信息结构
PerHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA)); // 在堆中为这个PerHandleData申请指定大小的内存
PerHandleData -> socket = acceptSocket;
memcpy (&PerHandleData -> ClientAddr, &saRemote, RemoteLen);
m_vclientGroup.push_back(PerHandleData); // 将单个客户端数据指针放到客户端组中
// 将接受套接字和完成端口关联
CreateIoCompletionPort((HANDLE)(PerHandleData -> socket), m_completionPort, (DWORD)PerHandleData, 0);
// 开始在接受套接字上处理I/O使用重叠I/O机制
// 在新建的套接字上投递一个或多个异步
// WSARecv或WSASend请求,这些I/O请求完成后,工作者线程会为I/O请求提供服务
// 单I/O操作数据(I/O重叠)
LPPER_IO_OPERATION_DATA PerIoData = NULL;
PerIoData = (LPPER_IO_OPERATION_DATA)GlobalAlloc(GPTR, sizeof(PER_IO_OPERATEION_DATA));
ZeroMemory(&(PerIoData -> overlapped), sizeof(OVERLAPPED));
PerIoData->databuff.len = 1024;
PerIoData->databuff.buf = PerIoData->buffer;
PerIoData->operationType = 0; // read
DWORD RecvBytes;
DWORD Flags = 0;
WSARecv(PerHandleData->socket, &(PerIoData->databuff), 1, &RecvBytes, &Flags, &(PerIoData->overlapped), NULL);
}
//销毁资源
DWORD dwByteTrans;
PostQueuedCompletionStatus(m_completionPort, dwByteTrans, 0, 0);
closesocket(listenResult);
return true;
}
/*********************
启动服务器
*********************/
bool CMYIOCPServer::ServerSetUp()
{
if(false == LoadWindowsSocket())
{
return false;
}
if(false == InitServerSocket())
{
return false;
}
if(false == CreateServerSocker())
{
return false;
}
return true;
}
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系SPASVO小编(021-61079698-8054),我们将立即处理,马上删除。

sales@spasvo.com