首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > .NET >

高性能大容量SOCKET并发(1):IOCP完成端口例子介绍

2013-01-07 
高性能大容量SOCKET并发(一):IOCP完成端口例子介绍提供服务和桌面方式运行,桌面方式可直接打开程序,方便日

高性能大容量SOCKET并发(一):IOCP完成端口例子介绍

    提供服务和桌面方式运行,桌面方式可直接打开程序,方便日常调试,可以使用命令行注册或卸载服务,在CMD中输入D:\DEMO\IOCPDemo\Bin\IOCPDemoSvr.exe -install来注册服务,在CMD输入D:\DEMO\IOCPDemo\Bin\IOCPDemoSvr.exe -uninstall来卸载服务。

客户端:

    界面截图如下:
    高性能大容量SOCKET并发(1):IOCP完成端口例子介绍
    主要实现了服务端日志查看,服务端协议类表查看,SQL语句执行协议,上传、下载协议实现,其中对上传、下载实现了一个多线程同时传,用于测试服务器并发性能。

性能:

    支持超过2000个链接及以上同时上传文件,不过每个连接上传速度只有1到2K。支持超过2W个连接同时在线传输命令。

单实例上传下载测试结果:
    高性能大容量SOCKET并发(1):IOCP完成端口例子介绍
    从测试结果可以看出随着发送包增大,速度变快。这里存在一个风险,就是SOCKET传输失败的次数也会增加。

下载地址:http://download.csdn.net/detail/sqldebug_fan/4510076
[解决办法]
这个要顶!支持技术分享!
[解决办法]
占个位置学习学习
高性能大容量SOCKET并发(1):IOCP完成端口例子介绍
[解决办法]
占个位置学习学习高性能大容量SOCKET并发(1):IOCP完成端口例子介绍
[解决办法]
高性能大容量SOCKET并发(1):IOCP完成端口例子介绍不錯,頂了
[解决办法]

引用:
博文源地址:http://blog.csdn.net/sqldebug_fan/article/details/7881793

最全介绍IOCP的例子,非常适合想了解IOCP编程人员。
Lz莫非是东莞的?又莫非是我同事?我们原来的三层用RO做的,现在公司的招了大牛研发IOCP,工资是我的三倍……下载学习下下。
[解决办法]
不错,谢谢。
有源码
[解决办法]
额,我觉得用IOCP来测试速度,好像是测试方向错误。。。

IOCP与其它模型,优点在于快速切换、连接之间的上下文处理,当然LZ用来测试速度也是一方面,但我怎么觉得LZ拿它作为主要的性能指标在折腾了?
[解决办法]
有源码吗,关于文件上传失败,怎么进行断点续传的。
[解决办法]
支持楼主 
[解决办法]
多谢楼主分享,几个问题咨询,服务器端:使用的内存池还是? 发送失败时或者发送部分出列时或者部分发送失败,怎么处理的? 执行GQCS(网络)的线程执行回调(或事件)还是线程池?大量使用EnterCriticalSection锁还是?如果是使用这个锁,分析过中锁概率没?连接池还是?广播时锁连接列表还是?

另,楼主可以这样测试IOCP效率,当收到一个完成数据包时(粘包后),把某个值+1,然后返回给客户端,客户端同样作这样的事情,这样这个数据包就一直来回传送,不停,多开几个客户端(并在不同的电脑上),放到1000M局网内跑,看服务器的总吞吐量,同时看CPU使用情况,这两个指标可以检查IOCP的设计性能,如果性能高,网络利用率80%以上,整体CPU使用率10%以内

共同探讨
[解决办法]
最近研究了公司的一个Iocp算是基本弄明白了


曾经有个哥们写聊天软件,他是一次分配好65535个对象,转发、广播都是通过查表实现,这样就巧妙的避免加锁问题,由于什么都是启动时分配,他也没有使用内存池

这和池的概念不是一样么
[解决办法]
不错不错,下来学习学习...
[解决办法]
犀利,收藏之
[解决办法]
你简直太可爱了。
谢谢楼主的无私啊。
[解决办法]
这个必须顶,不过就是贵点了
[解决办法]
厉害,不会delphi。
[解决办法]
用来传送文件,这个应用是个例而且和其他应用区别有点大,比如和大型网络游戏的区别就大了.



IOCP返回我是用大量的工作线程等待,类似线程池;
这就有一个问题,一个数据包接收后开始处理,未完成之前,是不能接收其他数据包的(因为WSARecv已经出列),更无法实现多通道工作,比如通道1提交传文件,通道2干点别的事情,也无法完成集结服务功能(客户端连接网关(假设可容纳5000连接),网关连接计算服务器(假设可容纳1-1000个网关),这样作的好处是,当用户量逐渐增加,就增加网关服务器即可,按照假设值最高就可以容纳5000*1000个用户,说白了这也是通道的一种应用。

开始IOCP时,申请大量的对象这个作法不错,一般也这么作,既然要上IOCP,连接2000以上时,占个1,2G的内存正常,对象本身要考虑记数即可

我的作法是,
  TSocketCtrl = packed record
    MemCtrl               : DWORD;           //内存控制,
    Data                  : PIOConnectInfo;   //连接数据
  end;
[MinSocket..MaxSocket] of TSocketCtrl
每次对MemCtrl执行原子操作来锁定和解锁,PIOConnectInfo则从内存池中获取,(这里值得探讨,因为Delphi的SysGetMem效率同样非常可观)
每一个Socket根据序号直接到达PSocketCtrl,然后原子锁定MemCtrl后即可操作内存(PIOConnectInfo),操作完后
原子解锁,当解锁后MemCtrl为0则释放连接数据(从内存池或者SysFreeMem)

我是一个较大的数来作为WSARecv入列记数(31位置1),其他锁定只+1,解锁只减1,如果MemCtrl<WSARecv入列记数,则不进行新的锁定(连接已经断开,等待释放内存),

内存占用是有点大....
[解决办法]
请教下楼主UDP是否适合使用IOCP?高性能大容量SOCKET并发(1):IOCP完成端口例子介绍
[解决办法]
请教下楼主UDP是否适合使用IOCP?
[解决办法]

引用:
用来传送文件,这个应用是个例而且和其他应用区别有点大,比如和大型网络游戏的区别就大了.

IOCP返回我是用大量的工作线程等待,类似线程池;
这就有一个问题,一个数据包接收后开始处理,未完成之前,是不能接收其他数据包的(因为WSARecv已经出列),更无法实现多通道工作,比如通道1提交传文件,通道2干点别的事情,也无法完成集结服务功能(客户端连接网关(假设可容纳5000连接),网关连接计算……


我是一个较大的数来作为WSARecv入列记数(31位置1),其他锁定只+1,解锁只减1,如果MemCtrl<WSARecv入列记数,则不进行新的锁定(连接已经断开,等待释放内存),
 
这个没太明白, 是不是类COM中的引用计数?
[解决办法]
引用:
请教下楼主UDP是否适合使用IOCP?


当然可以使用
[解决办法]
  pdRecvMark              = $80000000;      //接收入列 32位 置1

Function DoConnect(...
SC : PSocketCtrl
  SC := GetSocketCtrl(Socket..);//根据Socket返回控制阀
  ConnectData := PoolGetMemConnect();//连接需要的内存
  SC.Data := Connect;
  //LockCmpChange = LOCK CMPXCHG [ECX] , EDX
  if LockCmpChange(0 , pdRecvMark , @SC^.MemCtrl)<>0 then begin
      SC^.Data := NIL;
      PoolFreeMemConnect(Connect);
      ..DoError
  end;
DoConnect返回后,
WSARecv入列,如果出错,解锁,
客户端断开,或者出错时,GQCS需要执行UnLockConnectForRecv来解除接收锁定

发送数据时,执行LockConnectForSend,发送完成后(所有数据提交后都已经出列时)执行UnLockConnect,
当需要交叉使用时,如连接A发消息中转给连接B时,锁定B连接(LockConnect),即可


以下是加锁函数和解锁函数,任何要访问连接数据,都要先加锁



//发送锁定,只是比普通锁定更严格
Function LockConnectForSend(SC : PSocketCtrl) : PIOConnectInfo; 
asm
  MOV  ECX , EAX;                   //SC -> ECX
  @@DoLock:
  MOV  EAX , [ECX]                  //MemCtrl -> EAX


  CMP  EAX , pdRecvMark             //EAX < pdRecvMark, Recv已经出列,不再进行发送锁定,预比较
  JB   @@LockFaild                  //这里只做预判断,降低Lock使用概率
  MOV  EDX , EAX
  INC  EDX                          //记数器+1
  LOCK CMPXCHG [ECX] , EDX          //如果MemCtrl的值,还是=EAX(MemCtrl原值), 则用EDX(=EAX+1)代替
  JNZ  @@DoLock                     //如果EAX<>MemCtrl的原值,说明从把值取到EAX中后,有别的线程改变了MemCtrl的值,需要重新进行判断,反之,锁定成功,加个判断,虽然这种事情发生的概率非常非常小
  MOV  EAX , [ECX+4]                //锁定成功了,取值返回
  RET
  @@LockFaild:
  XOR  EAX , EAX                    //返回NIL
end;

//普通锁定连接内存
//只要MemCtrl<>0,都可以锁定后访问,目的是为了可能在断开后还能处理后续事情,区别于LockForSend
Function LockConnect(SC : PSocketCtrl) : PIOConnectInfo;
asm
  MOV  ECX , EAX
  @@DoLock:
  MOV  EAX , [ECX]                  //MemCtrl -> ECX
  TEST EAX , EAX                    //EAX =0 , 不进行锁定,预比较
  JZ   @@LockFaild                  //这里只做预判断,降低概率
  MOV  EDX , EAX
  INC  EDX
  LOCK CMPXCHG [ECX] , EDX
  JNZ  @@DoLock
  MOV  EAX , [ECX+4]
  RET
  @@LockFaild:
  XOR  EAX , EAX
end;

//解锁接收, fIOCP->EDX 该参数是传递给FreeConnectData使用的
procedure UnLockConnectForRecv(SC : PSocketCtrl; fIOCP : PIOCP_Server); assembler;
asm
  MOV  ECX , not pdRecvMark
  LOCK AND DWORD PTR [EAX] , ECX    //删除接收锁标记
  JNZ  @@Exit                       //结果为0,清除内存
    CALL FreeConnectData
  @@Exit:
end;

//普通解锁或者发送解锁,fIOCP->EDX 该参数是传递给FreeConnectData使用的
procedure UnLockConnect(SC : PSocketCtrl; fIOCP : PIOCP_Server); assembler;
asm
  LOCK DEC DWORD PTR [EAX]          //直接减1就解锁了
  JNZ  @@Exit
    CALL FreeConnectData
  @@Exit:
end;


[解决办法]
IOCP 没有那么神秘, 只是被神话了, iocp它可以高效的利用IO. 如果程序写的不合理, 即使使用了iocp一样是低效的
------解决方案--------------------


引用:
  pdRecvMark              = $80000000;      //接收入列 32位 置1

Function DoConnect(...
SC : PSocketCtrl
  SC := GetSocketCtrl(Socket..);//根据Socket返回控制阀
  ConnectData := PoolGetMemConnect();//连接需要的内存
……


为什么要搞的这么复杂呢
[解决办法]
越复杂越容易出现bug和错误
[解决办法]
引用:
为什么要搞的这么复杂呢

我能说什么呢,仁者见仁...
[解决办法]
引用:
引用:
为什么要搞的这么复杂呢

我能说什么呢,仁者见仁...


不用说什么, 只是很想了解一下你的想法和机制
[解决办法]
牛人啊,学习了。
[解决办法]
向楼主学习,技术第一
[解决办法]
向楼主学习,上面是我试试Ubb的
[解决办法]
不错,谢谢。
有源码
[解决办法]
很强大
[解决办法]
我的作法是,
  TSocketCtrl = packed record
  MemCtrl : DWORD; //内存控制,
  Data : PIOConnectInfo; //连接数据
  end;
[MinSocket..MaxSocket] of TSocketCtrl
每次对MemCtrl执行原子操作来锁定和解锁,PIOConnectInfo则从内存池中获取,(这里值得探讨,因为Delphi的SysGetMem效率同样非常可观)


高手啊  膜拜学习下
[解决办法]
IOCP真的就这么让你们崇拜?

不过是把大量IO操作的管理交给内核而已,然后通过线程调度的最合适数量原则提出了一个相对优化的线程方案,然后把所有的Socket的管理都交给了ComplationPort的内核对象管理。

IO模型最初级的就是select,select之后就是消息选择模型,然后是事件选择模型,通过这些模型完全可以套用IOCP的原理实现一个用户态的IOCP模型,只是性能还是要受限于用户态,所以再优化就是把整个模型所需要实现的基本框架放入内核,然后就有了现在的IOCP。IOCP对Socket和IO的管理方法并不高深,之所以让人觉得神秘是因为他是内核实现管理,给人一种看不到真面目的错觉,其实就相当于内核维护一个线程池,一个IO操作队列。

不要太迷信什么最牛比最牛逼,觉的不懂的往往是因为没有打算去搞懂,况且要想学会使用IOCP根本不需要了解上面所说。


[解决办法]
不是c++源码 是delph的吧
[解决办法]
引用:
不是c++源码 是delph的吧


    delphi板块,还会发C++么。
[解决办法]
不错,挺好。加油
[解决办法]
引用:
我的每次获取数据也是需要加锁的,是用了TCriticalSection对象,你的这个LockConnectForSend是使用计数器的方式?另外你保证原子性是如何做到的呢?


Function LockConnectForSend(SC : PSocketCtrl) : PIOConnectInfo; 
asm
...
  LOCK CMPXCHG [ECX] , EDX   <--原子操作
  //这里没直接LOCK INC [ECX],是因为这里是有条件的LOCK INC

[解决办法]
好厉害,膜拜
[解决办法]
一直感觉网络方面学习起来好无力,因为个人原因学习起来很难的。
------解决方案--------------------


delphi 的源码?
[解决办法]
进来向牛人学习
[解决办法]
感兴趣,先学习
[解决办法]
楼主 你把你代码里需要加锁的地方列出来看看, 哪些场景需要. 我目前就2个地方需要加个锁, 一个管理socket连接队列的地方, 一个是单socket发送数据队列. 
[解决办法]
谢谢楼主的分享,学习一下设计的思路。谢谢!
[解决办法]
我晕了,怎么是DELPHI的代码。。我还以为是。。
[解决办法]
谢谢楼主的分享,学习一下设计的思路。谢谢!学习.
[解决办法]
是delphi啊,我只能慢慢看了。。。
[解决办法]
谢谢分享!
[解决办法]
就是管理很多机器人嘛,不错。
[解决办法]

引用:
IOCP本身技术不复杂,迷人的是有很多策略需要选择,如工作线程个数、如何加锁、发送接收缓冲队列管理、内存分配这些每个都需要根据应用场景实时调整,也称为程序的纵向扩展。


楼主说的有道理,我不是搞Server的,我更偏向于Client,所以我们看问题可能就是两个方向了,你看的是这个模型的使用以及把这个模型放入一定的场景的适应和扩展能力,我看的只是这个模型内部的单单的实现原理。
[解决办法]
学习了那么好的东西,干货啊
[解决办法]
学习……学习……
[解决办法]
请教一个问题,独立线程Accept请求的效率与IOCP异步Accept的效率有多大差距?
[解决办法]
引用:
引用:
博文源地址:http://blog.csdn.net/sqldebug_fan/article/details/7881793

最全介绍IOCP的例子,非常适合想了解IOCP编程人员。
Lz莫非是东莞的?又莫非是我同事?我们原来的三层用RO做的,现在公司的招了大牛研发IOCP,工资是我的三倍……下载学习下下。


東莞厚街飄過!

[解决办法]
引用:
请教一个问题,独立线程Accept请求的效率与IOCP异步Accept的效率有多大差距?


我觉得和效率没什么关系,
IOCP 相对来说是减少Accept以后的工作线程个数
纯粹个人观点。 
[解决办法]
学习了解原理就可以了,现在很多开源的库已经做的很好了。比如boost的asio
[解决办法]
引用:
请教下楼主UDP是否适合使用IOCP?


跟协议无关,涉及IO都可以使用,不过对于UDP,使用IOCP意义不大
[解决办法]
引用:
请教一个问题,独立线程Accept请求的效率与IOCP异步Accept的效率有多大差距?


我个人的感觉 异步accept是用来解决高并发连接的, 单线程肯定没有多投递来的快, 毕竟后备socket队列在不同的操作系统上都大不, 貌似xp才200个

热点排行