如何使用c++,借助完成端口完成大并发服务器的搭建,是今天要讨论的问题,套路如下:


套路总结一下:
创建完成端口
依据CPU核数创建一定数量的线程
线程中不断调用GetQueuedCompletionStatus检查完成端口状态,分别给予处理
创建一个socket,绑定IP和端口
将这个socket绑定到第一步创建的完成端口上





获取当前服务器的CPU核数,根据核数创建一定数量的线程









GetQueuedCompletionStatus这个函数非常重要,上面创建的线程不断检查完成端口的状态,有则处理


void CIocpCtrl::OnExecute()
{SPerHandleData* pstPerHandleData;SPerIoData*     pstPerIoData;CCPSock*        poSock;CCpListener*    poListener;BOOL            bRet;DWORD           dwByteTrabsferred;//通过while(true)循环,不断的检查while(true) {pstPerHandleData    = NULL;pstPerIoData        = NULL;dwByteTrabsferred   = 0;//最重要的就是GetQueuedCompletionStatus这个函数bRet = GetQueuedCompletionStatus(m_hCompletionPort,&dwByteTrabsferred,(PULONG_PTR)&pstPerHandleData,(LPOVERLAPPED*)&pstPerIoData,INFINITE);// 检查是否是线程退出if(NULL == pstPerHandleData){return;}if(pstPerHandleData->bListen){// for listen eventpoListener = (CCpListener*)pstPerHandleData->ptr; //注意这里if(NULL != poListener &&  NULL != pstPerIoData){poListener->OnAccept(bRet, pstPerIoData); //接收一个新连接}else {SDASSERT(false);}}else {//for non-listen event poSock = (CCPSock*)pstPerHandleData->ptr; //注意这里if ( NULL == poSock ){continue;}if( FALSE == bRet || NULL == pstPerIoData ){               if (::WSAGetLastError()!=ERROR_IO_PENDING){INFO(_SDT("[%s:%d]CCPSock connID=%d error %d, close it"), MSG_MARK, poSock->GetConnectionID(), ::WSAGetLastError());poSock->OnClose();}               }else{       //判断类型switch(pstPerIoData->nOp){case IOCP_RECV:{poSock->DecPostRecv();if (dwByteTrabsferred > 0){poSock->OnRecv(dwByteTrabsferred); //处理接收到的数据}else{INFO(_SDT("[%s:%d]CCPSock connID=%d error %d, close it, socket :%d "), MSG_MARK, poSock->GetConnectionID(), ::WSAGetLastError(), poSock->GetSock());poSock->OnClose();}}break;case IOCP_SEND:{poSock->DecPostSend();if (dwByteTrabsferred > 0){poSock->OnSend(dwByteTrabsferred); //处理发送的数据}else{INFO(_SDT("[%s:%d]CCPSock connID=%d error %d, close it"), MSG_MARK, poSock->GetConnectionID(), ::WSAGetLastError());poSock->OnClose();}}break;case IOCP_CLOSE:{poSock->OnClose(false); //关闭连接}break;default:;}}}}
}

//提供一个入口,供其它socket绑定完成端口
bool CIocpCtrl::AssociateWithIocp(SOCKET hSock, SPerHandleData* pstData)
{if (NULL == m_hCompletionPort){return false;}if(NULL == CreateIoCompletionPort((HANDLE)hSock, m_hCompletionPort, (ULONG_PTR)pstData, 0)){WARN(_SDT("CIocpCtrl::AssociateWithIocp, failed, errno %d"), WSAGetLastError());return false;}return true;
}

下面就是一个接收处理:

void CCpListener::OnAccept(BOOL bSucc, SPerIoData* pstPerIoData)
{SOCKET hSock = pstPerIoData->hSock; //取出socketif(false == m_bStart){InterlockedIncrement((volatile LONG*)&m_dwReleaseCount);closesocket(hSock);return;}this->PostAcceptEx(pstPerIoData); //接收一个连接之后,就要顺道再投递一个AcceptEx if(FALSE == bSucc){WARN(_SDT("CCpListener::OnAccept, accept failed, errno %d"), ::WSAGetLastError());closesocket(hSock);}else{//下面就是封装这个连接,以及在这个新连接上投递接收请求CConnData* pConnData = CConnDataMgr::Instance()->Alloc(m_dwRecvBufSize, m_dwSendBufSize);CCPSock * poSock = &pConnData->sock;        CUCConnection* poConnection = & pConnData->connection;//+lcjif (0 != ::setsockopt(hSock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char *)&m_hListenSock, sizeof(SOCKET))){WARN(_SDT("setsockopt for new socket on UpdateConetext failed, errno=%d"), ::WSAGetLastError());}if (g_bNodelay){const CHAR szOpt = 1;if (0 != ::setsockopt(hSock, IPPROTO_TCP, TCP_NODELAY, (char *)&szOpt, sizeof(char))){WARN(_SDT("setsockopt for new socket on UpdateConetext failed, errno=%d"), ::WSAGetLastError());}}poSock->SetSock(hSock);poSock->SetPacketParser(m_poPacketParser);poConnection->SetAccept(true);poConnection->SetParentID(0);sockaddr_in RemoteAddr, LocalAddr;GetSockAddress(pstPerIoData, RemoteAddr, LocalAddr);poConnection->SetLocalIP(LocalAddr.sin_addr.s_addr);poConnection->SetLocalPort(SDNtohs(LocalAddr.sin_port));poConnection->SetRemoteIP(RemoteAddr.sin_addr.s_addr);poConnection->SetRemotePort(SDNtohs(RemoteAddr.sin_port));//注意这里,session和Connection连接起来ISDSession* poSession = m_poSessionFactory->CreateSession(poConnection);if(NULL == poSession){DBG(_SDT("CCpListener::OnAccept, CreateSession failed"));closesocket(hSock);CConnDataMgr::Instance()->Release(pConnData);return;}poConnection->SetSession(poSession);poSock->SetConnect(TRUE);
#ifndef SDENT_HAS_RECV_QUEUEpoConnection->OnAssociate();
#endifif(false == poSock->AssociateWithIocp()) //将新接收的socket绑定完成端口{poSock->DoClose();}else{if(false == poSock->PostRecv()) //投递一个接收请求{poSock->DoClose();}}}




FR:海涛高软(hunk Xu)

c++使用完成端口实现服务器的高性能并发相关推荐

  1. 服务器型号 数量和配置,一配置总体情况设备名称设备配置数量服务器HPDL580G7高性能.doc...

    一配置总体情况设备名称设备配置数量服务器HPDL580G7高性能 一:配置总体情况 设备名称设备配置数量服务器HP DL 580 G7高性能服务器,配置4颗8核4820处理器(2.0GHz, 18MB ...

  2. 高性能服务器存储服务器,高性能存储服务器

    高性能存储服务器 内容精选 换一换 云硬盘(Elastic Volume Service, EVS)可以为云服务器提供高可靠.高性能.规格丰富并且可弹性扩展的块存储服务,可满足不同场景的业务需求,适用 ...

  3. scp 、ssh非22端口的服务器方法

    ssh 连接远程ssh非22端口服务器的方法 #ssh -p 2000 weijunping@10.32.0.228 scp 远程拷贝ssh非22端口的服务器文件使用方法 #scp -P 2000 a ...

  4. SSL使用什么端口?服务器端口对于SSL的重要性

    SSL使用什么端口?在了解这个问题之前,先带大家来认识一下端口是什么. 在这个互联网发达的时代,我们平常的工作.生活大部分都是依靠网络.当我们通过计算机发出一些请求,计算机都会通过某一个特定的通道来进 ...

  5. 你需要知道的高性能并发框架Disruptor原理

    Disruptor的小史 现在要是不知道Disruptor真的已经很outer了,Disruptor是英国外汇交易公司LMAX开发的一款开源的高性能队列,LMAX Disruptor是一个高性能的线程 ...

  6. 如何用Python一门语言通吃高性能并发、GPU计算和深度学习

    [CTO讲堂]如何用Python一门语言通吃高性能并发.GPU计算和深度学习 发表于2016-01-04 15:11| 4374次阅读| 来源CSDN| 4 条评论| 作者蒲婧 CTO俱乐部CTOCT ...

  7. 网络编程释疑之:单台服务器上的并发TCP连接数可以有多少

    曾几何时我们还在寻求网络编程中C10K问题的解决方案,但是现在从硬件和操作系统支持来看单台服务器支持上万并发连接已经没有多少挑战性了. 我们先假设单台服务器最多只能支持万级并发连接,其实对绝大多数应用 ...

  8. 高性能并发TCP网络服务-IOCP框架修正VC2008版本

    From: http://blog.csdn.net/lsfa1234/article/details/6223635 高性能并发TCP网络服务IOCP框架修正VC2008版本 从Source Cod ...

  9. 一般云服务器支持多少并发,一般云服务器支持是多大并发?

    云服务器支持是多少并发,换句话说云服务器最多能支持多少人同时在线,这个问题是没法获得一个精确回答的.由于結果会遭受带宽.网络服务器响应速度.不一样客户已经浏览的网页页面大小等一系列要素的限定,而这种全 ...

  10. java 并发框架源码_Java并发编程高阶技术-高性能并发框架源码解析与实战

    Java并发编程高阶技术-高性能并发框架源码解析与实战 1 _0 Z' @+ l: s3 f6 r% t|____资料3 Z9 P- I2 x8 T6 ^ |____coding-275-master ...

最新文章

  1. 计算机函数模式的用处是啥,请问怎么理解计算机中的函数?
  2. KVM虚拟化存储管理
  3. toad dba suite for oracle 12.1,Toad for Oracle 12.1下载地址
  4. python大全1015python大全_python 列表总结大全
  5. 数据结构之堆的插入、取值、排序(细致讲解+图片演示)
  6. 清理AD过期对象,并将结果发送给指定管理员
  7. html中怎么修改黑体,css怎样设置黑体?
  8. P3802 小魔女帕琪
  9. 《麦肯锡方法》读书笔记10
  10. c# 对一个数组进行随机排序
  11. CSDN博文精选:最受欢迎的系列专栏博客推荐
  12. 方格网提取高程点lisp_基于VBA的道路横断面高程点提取方法研究
  13. 磁阻随机存储器(MRAM)市场现状研究分析与发展前景预测报告
  14. MATLAB启动慢解决方案
  15. 语音芯片选型基础,如何计算声音文件的大小?
  16. 简易爬虫---爬图片以及用到的主要知识
  17. SDUT ACM 多项式求和(基于C语言)
  18. 2015 macbook air换第三方SSD(西数SN750)
  19. 线性代数的一些知识点
  20. 联想手机吹响反攻号角,“诺曼底计划”未来要剑指何方?

热门文章

  1. Microchip PIC系列8位单片机入门教程(二)点亮LED灯
  2. matlab瑞利衰落信道仿真
  3. clearcase 操作指南
  4. 数字电路-时序逻辑电路
  5. 钉钉日志范文100篇_关于公司各岗位钉钉日志撰写标准
  6. springboot毕业实习信息管理系统的设计与实现
  7. unity3d:激活码系统(根据PC机器码,给对应激活码完成软件注册)
  8. mw150um 驱动程序win10_Intel网卡驱动Win10官方下载_Intel网卡驱动Win10专版64位官方安装版-华军软件园...
  9. 实时记录运动轨迹插件_浅谈 leaflet 地图插件的使用(制作飞机航线图)
  10. win10语言不能安装计算机,解决win10添加语言包失败提示错误代码:0x800F0950的方法...