完成端口代码

小猪IOCP源码解析:完成端口实现高并发异步I/O 高并发网络编程中,阻塞线程与select模型在连接数上升后都会遭遇资源瓶颈。IOCP(完成端口)作为Windows平台的高性能异步I/O模型,通过内核完成队列将I/O事件直接分发给工作线程,线程数仅与CPU核数相关,从而支撑上万级连接。理解完成键、OVERLAPPED和缓冲池的所有权流转,是正确实现收发与避免内存错乱的关键。该模型广泛应用于游戏服务器、IM推送、实时行情等场景。本文基于小猪IOCP工程源码,讲解完成端口初始化、工作线程循环、粘包拆包、发送队列管理及优雅关闭流程,并总结了高并发环境下的典型踩坑 阅读详情
//采用完成端口的代理服务器原型代码  
http://www.vckbase.com/code/listcode.asp?mclsid=9&sclsid=901  
 
---------------------------------------------------------------  
 
http://www.vctop.com/View.Asp?ID=484&CateID=1  
---------------------------------------------------------------  
 
服务器程序:  
http://www.cnxbb.com/bcb/xbb_server_iocp.rar  
 
模拟多客户端程序  
http://www.cnxbb.com/bcb/EchoClient.rar  
---------------------------------------------------------------  
 
//  Compile:  
//  
//        cl  -o  callback  callback.cpp  ws2_32.lib  
//  
//  Command  Line  Options:  
//  
//        callback.exe    
//  
//        Note:  There  are  no  command  line  options  for  this  sample.  
 
//  
//  阻塞模式+重叠模型+完成例程机制,王天平,2003-06-20  
//  
 
#include  <winsock2.h>  
#include  <windows.h>  
#include  <stdio.h>  
 
#define  PORT  5150  
#define  DATA_BUFSIZE  8192  
 
//套接字信息数组单元结构  
typedef  struct  _SOCKET_INFORMATION  {  
     OVERLAPPED  Overlapped;//重叠结构  
     SOCKET  Socket;//套接字  
     CHAR  Buffer[DATA_BUFSIZE];//WSARecv/WSASend  数据缓冲区指针  
     WSABUF  DataBuf;//WSARecv/WSASend  数据缓冲区  
     DWORD  BytesSEND;//发送字节数  
     DWORD  BytesRECV;//接收字节数  
}  SOCKET_INFORMATION,  *  LPSOCKET_INFORMATION;  
 
void  CALLBACK  WorkerRoutine(DWORD  Error,  DWORD  BytesTransferred,  
     LPWSAOVERLAPPED  Overlapped,  DWORD  InFlags);  
 
DWORD  WINAPI  WorkerThread(LPVOID  lpParameter);  
 
SOCKET  AcceptSocket;  
 
void  main(void)  
{  
     WSADATA  wsaData;  
     SOCKET  ListenSocket;  
     SOCKADDR_IN  InternetAddr;  
     INT  Ret;  
     HANDLE  ThreadHandle;  
     DWORD  ThreadId;  
     WSAEVENT  AcceptEvent;  
 
     if  ((Ret  =  WSAStartup(0x0202,&wsaData))  !=  0)  
     {  
           printf("WSAStartup  failed  with  error  %d/n",  Ret);  
           WSACleanup();  
           return;  
     }  
 
     if  ((ListenSocket  =  WSASocket(AF_INET,  SOCK_STREAM,  0,  NULL,  0,    
           WSA_FLAG_OVERLAPPED))  ==  INVALID_SOCKET)    
     {  
           printf("Failed  to  get  a  socket  %d/n",  WSAGetLastError());  
           return;  
     }  
 
     InternetAddr.sin_family  =  AF_INET;  
     InternetAddr.sin_addr.s_addr  =  htonl(INADDR_ANY);  
     InternetAddr.sin_port  =  htons(PORT);  
 
     if  (bind(ListenSocket,  (PSOCKADDR)  &InternetAddr,  
           sizeof(InternetAddr))  ==  SOCKET_ERROR)  
     {  
           printf("bind()  failed  with  error  %d/n",  WSAGetLastError());  
           return;  
     }  
 
     if  (listen(ListenSocket,  5))  
     {  
           printf("listen()  failed  with  error  %d/n",  WSAGetLastError());  
           return;  
     }  
 
     if  ((AcceptEvent  =  WSACreateEvent())  ==  WSA_INVALID_EVENT)  
     {  
           printf("WSACreateEvent()  failed  with  error  %d/n",  WSAGetLastError());  
           return;  
     }  
 
     //  Create  a  worker  thread  to  service  completed  I/O  requests.    
 
     if  ((ThreadHandle  =  CreateThread(NULL,  0,  WorkerThread,  (LPVOID)  AcceptEvent,  0,  &ThreadId))  ==  NULL)  
     {  
           printf("CreateThread  failed  with  error  %d/n",  GetLastError());  
           return;  
     }  
 
     while(TRUE)  
     {  
           AcceptSocket  =  accept(ListenSocket,  NULL,  NULL);  
 
           if  (WSASetEvent(AcceptEvent)  ==  FALSE)  
           {  
                 printf("WSASetEvent  failed  with  error  %d/n",  WSAGetLastError());  
                 return;  
           }  
     }  
}  
 
DWORD  WINAPI  WorkerThread(LPVOID  lpParameter)  
{  
     DWORD  Flags;  
     LPSOCKET_INFORMATION  SocketInfo;  
     WSAEVENT  EventArray[1];  
     DWORD  Index;  
     DWORD  RecvBytes;  
 
     //  Save  the  accept  event  in  the  event  array.  
 
     EventArray[0]  =  (WSAEVENT)  lpParameter;  
 
     while(TRUE)  
     {  
           //  Wait  for  accept()  to  signal  an  event  and  also  process  WorkerRoutine()  returns.  
 
           while(TRUE)  
           {  
                 Index  =  WSAWaitForMultipleEvents(1,  EventArray,  FALSE,  WSA_INFINITE,  TRUE);  
 
                 if  (Index  ==  WSA_WAIT_FAILED)  
                 {  
                       printf("WSAWaitForMultipleEvents  failed  with  error  %d/n",  WSAGetLastError());  
                       return  FALSE;  
                 }  
 
                 if  (Index  !=  WAIT_IO_COMPLETION)  
                 {  
                       //  An  accept()  call  event  is  ready  -  break  the  wait  loop  
                       break;  
                 }    
           }  
 
           WSAResetEvent(EventArray[Index  -  WSA_WAIT_EVENT_0]);  
       
           //  Create  a  socket  information  structure  to  associate  with  the  accepted  socket.  
 
           if  ((SocketInfo  =  (LPSOCKET_INFORMATION)  GlobalAlloc(GPTR,  
                 sizeof(SOCKET_INFORMATION)))  ==  NULL)  
           {  
                 printf("GlobalAlloc()  failed  with  error  %d/n",  GetLastError());  
                 return  FALSE;  
           }    
 
           //  Fill  in  the  details  of  our  accepted  socket.  
 
           SocketInfo->Socket  =  AcceptSocket;  
           ZeroMemory(&(SocketInfo->Overlapped),  sizeof(WSAOVERLAPPED));      
           SocketInfo->BytesSEND  =  0;  
           SocketInfo->BytesRECV  =  0;  
           SocketInfo->DataBuf.len  =  DATA_BUFSIZE;  
           SocketInfo->DataBuf.buf  =  SocketInfo->Buffer;  
 
           Flags  =  0;  
           if  (WSARecv(SocketInfo->Socket,  &(SocketInfo->DataBuf),  1,  &RecvBytes,  &Flags,  
                 &(SocketInfo->Overlapped),  WorkerRoutine)  ==  SOCKET_ERROR)  
           {  
                 if  (WSAGetLastError()  !=  WSA_IO_PENDING)  
                 {  
                       printf("WSARecv()  failed  with  error  %d/n",  WSAGetLastError());  
                       return  FALSE;  
                 }  
           }  
 
           printf("Socket  %d  connected/n",  AcceptSocket);  
     }  
 
     return  TRUE;  
}  
 
void  CALLBACK  WorkerRoutine(DWORD  Error,  DWORD  BytesTransferred,  
     LPWSAOVERLAPPED  Overlapped,  DWORD  InFlags)  
{  
     DWORD  SendBytes,  RecvBytes;  
     DWORD  Flags;  
 
     //  Reference  the  WSAOVERLAPPED  structure  as  a  SOCKET_INFORMATION  structure  
     LPSOCKET_INFORMATION  SI  =  (LPSOCKET_INFORMATION)  Overlapped;  
 
     if  (Error  !=  0)  
     {  
         printf("I/O  operation  failed  with  error  %d/n",  Error);  
     }  
 
     if  (BytesTransferred  ==  0)  
     {  
           printf("Closing  socket  %d/n",  SI->Socket);  
     }  
 
     if  (Error  !=  0    ¦  ¦  BytesTransferred  ==  0)  
     {  
           closesocket(SI->Socket);  
           GlobalFree(SI);  
           return;  
     }  
 
     //  Check  to  see  if  the  BytesRECV  field  equals  zero.  If  this  is  so,  then  
     //  this  means  a  WSARecv  call  just  completed  so  update  the  BytesRECV  field  
     //  with  the  BytesTransferred  value  from  the  completed  WSARecv()  call.  
 
     if  (SI->BytesRECV  ==  0)  
     {  
           SI->BytesRECV  =  BytesTransferred;  
           SI->BytesSEND  =  0;  
     }  
     else  
     {  
           SI->BytesSEND  +=  BytesTransferred;  
     }  
 
     if  (SI->BytesRECV  >  SI->BytesSEND)  
     {  
 
           //  Post  another  WSASend()  request.  
           //  Since  WSASend()  is  not  gauranteed  to  send  all  of  the  bytes  requested,  
           //  continue  posting  WSASend()  calls  until  all  received  bytes  are  sent.  
 
           ZeroMemory(&(SI->Overlapped),  sizeof(WSAOVERLAPPED));  
 
           SI->DataBuf.buf  =  SI->Buffer  +  SI->BytesSEND;  
           SI->DataBuf.len  =  SI->BytesRECV  -  SI->BytesSEND;  
 
           if  (WSASend(SI->Socket,  &(SI->DataBuf),  1,  &SendBytes,  0,  
                 &(SI->Overlapped),  WorkerRoutine)  ==  SOCKET_ERROR)  
           {  
                 if  (WSAGetLastError()  !=  WSA_IO_PENDING)  
                 {  
                       printf("WSASend()  failed  with  error  %d/n",  WSAGetLastError());  
                       return;  
                 }  
           }  
     }  
     else  
     {  
           SI->BytesRECV  =  0;  
 
           //  Now  that  there  are  no  more  bytes  to  send  post  another  WSARecv()  request.  
 
           Flags  =  0;  
           ZeroMemory(&(SI->Overlapped),  sizeof(WSAOVERLAPPED));  
 
           SI->DataBuf.len  =  DATA_BUFSIZE;  
           SI->DataBuf.buf  =  SI->Buffer;  
 
           if  (WSARecv(SI->Socket,  &(SI->DataBuf),  1,  &RecvBytes,  &Flags,  
                 &(SI->Overlapped),  WorkerRoutine)  ==  SOCKET_ERROR)  
           {  
                 if  (WSAGetLastError()  !=  WSA_IO_PENDING  )  
                 {  
                       printf("WSARecv()  failed  with  error  %d/n",  WSAGetLastError());  
                       return;  
                 }  
           }  
     }  
}  
博客文章《完成端口详解》配套代码 这份代码是我博客里的文章《完成端口详解 - 手把手教你玩转网络编程系列之三》的配套代码 里面的代码包括VC++2008/VC++2010编写的完成端口服务器端的代码,还包括一个对服务器端进行压力测试的客户端,都是经过我精心调试过,并且带有非常详尽的代码注释的。当然,作为教学代码,为了能够使得代码结构清晰明了,我还是对代码有所简化,如果想要用于产品开发,最好还是需要自己再完善一下 详情请参见我的博客 http://blog.youkuaiyun.com/piggyxp 立即下载

相关推荐

完成端口IOCP示例代码

完成端口示例代码,包括用于测试的客户端代码。 是PiggyXP写的,大家可以配合PiggyXP的博客一起看 博客地址: http://blog.youkuaiyun.com/piggyxp/article/details/6922277 ps.我看了PiggyXP该资源下载得分已经超过上限,我转载不会影响PiggyXP获取下载积分,就转来赚一点积分。

完成端口模型代码

最近要做一个网络方面的小东东,基于C/S模式的。都说IOCP可以使系统达到最佳的性能,因此我就比划了两下,献丑了。抄书开始。    从本质上说,完成端口模型要求创建一个windows完成端口对象,该对象通过指定数量的线程,对重叠I/O请求进行管理,以便为已经完成的重叠I/O请求提供服务。    首先要创建一个I/O完成端口对象,用它面向任意数量的套接字句柄,管理多个I/O请求。调用以下函数创建完成

hbyh的专栏 1098

完成端口详解配套代码

小猪完成端口详解的配套代码,以及包含的服务器压力测试的简单客户端软件。

网络编程 完成端口模型

网络编程 完成端口模型

weixin_62859191的博客 1341

小猪完成端口文章及源码

《手把手叫你玩转网络编程系列之三 完成端口(Completion Port)详解》By PiggyXP(小猪) 文章内容和源码。 原文地址: http://blog.youkuaiyun.com/piggyxp/article/details/6922277

PiggyXP 完成端口的源码

作者原来的项目代码已经不能下载了,这里补上, 作者文章地址:http://blog.youkuaiyun.com/piggyxp/article/details/6922277 包含以下文件 IOCPExample_By_PiggyXP.rar PiggyStressTestClient.rar

完成端口(CompletionPort)详解 - 手把手教你玩转网络编程系列之三

手把手叫你玩转网络编程系列之三    完成端口(Completion Port)详解                                                              ----- By PiggyXP(小猪) 前 言         本系列里完成端口的代码在两年前就已经写好了,但是由于许久没有写东西了,不知该如何提笔,所以这篇文档总是在酝酿

小猪的网络编程 22万+

行人重识别(ReID)基础知识入门

行人重识别(Person re-identification)主要目的是针对出现在监控摄像头内的某个目标行人,准确快速地从监控网络其他摄像头内的大量行人中将这个目标行人标识出来。如图所示一个区域有多个摄像头拍摄视频序列,ReID的要求对一个摄像头下感兴趣的行人,检索到该行人在其他摄像头下出现的所有图片。

用于记录 1万+

完成端口(CompletionPort)详解

     手把手叫你玩转网络编程系列之三    完成端口(Completion Port)详解                      &...

欧特GO 1083

Verilog除法器(32位无符号+带符号)

32位无符号除法器设计 恢复余数法: 恢复余数除法的基本思路是从“部分余数”中减去除数,如果结果为负(不够减),则恢复原来的部分余数,商0. 寄存器使用: reg_r 存放被除数a reg_b 存放除数b reg_r 存放余数(初始清零) 具体做法: 做减法时,减数是reg_b中的除数,被减数是reg_r中的余数左移一位,最低位由reg_q(被除数)的最高位补充。为了能够判断相减结果的正...

qq_38600065的博客 1万+

波束形成算法:LCMV实现(MATLAB)

阵列信号处理,波束成形,

weixin_43601588的博客 1万+

《完成端口详解》配套代码:网络编程的进阶利器

《完成端口详解》配套代码:网络编程的进阶利器 去发现同类优质开源项目:https://gitcode.com/ 项目介绍 你是否在网络编程的道路上感到迷茫?是否对完成端口(IOCP)这一高级网络编程技术感到困惑?《完成端口详解》配套代码正是为你量身打造的进阶工具。这份代码不仅是我博客文章《完成端口详解 - 手把手教你玩转网络编程系列之三》的完美补充,更是你深入理解并掌握完成端口技术的最佳实践。 项...

gitblog_09765的博客 504

若依(RuoYi)框架从零到部署:Spring Boot+Vue权限系统完整配置指南

在Java企业级应用开发中,Spring Boot作为构建微服务和单体应用的基石,极大地简化了项目初始化和配置流程。其核心原理在于通过自动配置和起步依赖,快速整合数据访问、安全认证、缓存等常用模块,显著提升开发效率。这一技术价值在需要快速构建后台管理系统的场景中尤为突出,例如权限管理、用户角色分配等通用需求。若依(RuoYi)框架正是基于Spring Boot和Vue.js的优秀实践,它封装了RBAC权限模型、代码生成器等高频功能,提供了开箱即用的解决方案。本文聚焦于若依框架的【环境配置】与【项目部署】,通

weixin_33984032的博客 455

Winsock完成端口模型-Delphi代码

 原文出处 《Windows网络编程技术》第8章 完成端口模型 由于原书附的是C代码,我把其翻译成Delphi代码。   其中winsock2.pas在delphi中不带,要另外下载http://jungla.dit.upm.es/~bti/files/winsock2.pas     program CompletionIO; {$AP

技术天地 4492

旋转矩阵推导

推导前提: 坐标使用右手坐标系,角度逆时针旋转为正。 绕X轴旋转角度为 俯仰角 即Pitch 绕Y轴旋转角度为 偏航角 即Yaw(Head) 绕Z轴旋转角度为 翻滚角 即Roll 一、平面二维坐标点的旋转 如右图所示,根据三角函数关系,可以列出向量OP与OP’的坐标表示形式: x = |OP|•cosα x′ = |OP|•cos(α+β) y = |OP|•sinα y′ = |OP|•sin(α+β) 将P′(x′,y′)表达式展开: x′ =

suixinger_lmh的随笔 1384

SAP特殊采购类80实战:跨工厂生产配置避坑指南(附完整测试流程)

本文深入解析SAP特殊采购类80在跨工厂生产场景下的实战应用与配置要点。文章从核心业务逻辑出发,详细拆解了后台配置、主数据与BOM的“双工厂”思维模式,并提供了从创建需求到成品收货的完整测试流程。重点揭示了多层BOM下的需求传递陷阱及常见报错解决方案,旨在帮助SAP顾问及用户规避实施风险,实现资源的灵活调度与流程自动化。

wind6的博客 1139

最简单的完成端口代码

一起来分析一下最简单的完成端口代码#include<winsock2.h>#include<windows.h>#include<stdio.h>#include<assert.h> #include"Socket5.h" voidmain(void){//变量声明WSADATAwsaData;DWORDRet;HANDLE...

weixin_34095889的博客 223

excel 利用SUBTOTAL函数计算筛选后数列总和、均值、最大、最小值

表里有三个人,咱们需要筛选出三个人,并分别计算他们的总和值。 先看一下数据范围(A1:B27) 通过筛选找张三。 按照上图所示输入函数,选择9,求和。 然后按照函数输入即可。 就能计算出结果。 筛选项选择王五,就会自动计算王五的总和。 筛选到李四就会自动计算李四的总和。 如果把9改成1,就是自动计算筛选出来的均值结果,如下图所示。 如果改成4就是取筛选项的最大值,选择5就是取最小值。 ...

yuanYW7556的博客 3万+

完成端口的部分代码

 //完成端口的部分代码//主线程//创建原始完成端口句柄hIOCP=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);if(NULL==hIOCP){ //错误处理}//创建监听套节字 ListenPort()封装了bind listen等函数SocketListen=Listen

604

告别环境配置烦恼:Docker容器化一站式搭建Zephyr RTOS开发环境

本文详细介绍了如何使用Docker容器化技术一站式搭建Zephyr RTOS开发环境,彻底解决环境配置不一致、依赖冲突等难题。通过预构建镜像、数据卷挂载和实战编译示例,帮助开发者快速获得隔离、一致且可复现的嵌入式开发环境,大幅提升开发效率和团队协作体验。

n8m7b6v5c4的博客 189

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

使用完成端口HTTP下载的代码

使用完成端口HTTP下载的代码(转载请注明来源于金庆的专栏) 试运行asio的async_client例程时,发现CPU占用很高,所以又写了一个相同功能但直接调用完成端口API的代码,进行比较,发现同样占用CPU。与flashget比较,下载速度差不多,但flashget不占CPU。将直接API调用代码和利用asio的代码都列在下面。进行测试时,要将其中的参数定义改改,如SERVER参数。并且要找...

luliangok 114

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

初学完成端口的实例代码

////////////////////////////////////////////////////////////////////////////  完成端口//////////////////////////////////////////////////////////////////////////////#include "stdafx.h"#include #include #

程序的江湖?! 勿在浮砂筑高台! 1864

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

C#实现IOCP(完成端口)的详细代码示例

C#实现IOCP(完成端口)的详细代码如下: using System; using System.Threading; // Included for the Thread.Sleep call using Continuum.Threading; namespace Sample { //=========================================...

weixin_30657999的博客 281
上一篇: 理解I/O Completion Port
下一篇: 完成端口重叠I/O模型的服务器中,存储和管理数万个socket句柄
Garfield
博客等级 码龄26年 24粉丝 29原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值