为何IOCP能够同时处理成千上万个连接???(20分)

  • 主题发起人 主题发起人 mill666
  • 开始时间 开始时间
[:D]少唬人了.
ISCSI网络存储方案用驱动是不得已而为之,如果能在上层完成,不可能用驱动.而且网络存储方案主要是因为文件过滤部分需要用驱动.
"入侵检测集群,联动防火墙内部的通讯就更不用讲了,肯定用驱动来收发数据包"这个跟通信完全是两回事情吧,只是检测数据包而已.

"甚至我们大家都知道WinpCap方案都在使用驱动来做直接通讯"
这个就更加错误了.一般很少(几乎没有)人用它来直接做通讯,最明显一个原因就是TCP协议栈的问题.所以一般只是用来做SNIFF之类,因为网卡会把非发送给本机的数据丢弃,所以是不得已而为之.如果能直接在上层拦截数据,经过WINDOWS自身协议层得到完整的数据包,谁会用WinPCap?

不知道谁见识少.WINPCAP早几年就用过了,当时主要是拦截修改数据包,部分代码段(只是很少部分,你可以看出要自己用WINPCAP收发数据是多少麻烦的事情):

//发现有局部网电脑下载文件,那么给下载欺骗服务器发送SYN,模拟客户端连接,进行会话劫持,将文件内容替换成我们的:
SendTcpFlagToDestMACAndIP(
PORT_HTTP, //dest port
punsigned_char(@pConnect^.ServerMAC), //dest mac
inet_addr(SnoopServerIP), //dest ip
pConnect^.vport, //src port
inet_addr(VirualClientIP), //src ip
punsigned_char(@g_szOwnMAC), //src mac
SYN,
htonl(pConnect^.seq - 1),
0,
htons(pConnect^.ident - 2),
WINSIZE, TRUE, ThreadNo);

{$IFDEF TRACELOG}
TRACELOG('给下载欺骗服务器重发SYN,模拟客户端连接,进行会话劫持');
{$ENDIF}

Result := TRUE; Exit;
end
else if (pConnect^.Flag = $03) then
begin
usIPHeadLen := (pTempletPacket^.iphdr.h_verlen and $0F) * sizeof(unsigned_long);
usTCPHeadLen := ((pTempletPacket^.tcphdr.th_lenres shr 4) and $0F) * sizeof(unsigned_long);
iTcpDataLen := ntohs(pTempletPacket^.iphdr.total_len) - usIPHeadLen - usTCPHeadLen;
pTcpData := pchar(pTempletPacket) + sizeof(TEHHDR) + usIPHeadLen + usTCPHeadLen;

其中TCP协议栈是直接移植单片机上面的.结合硬件进行SNIFF ADSL上网数据并修改数据再回传的我们也做过.还有一个项目是直接走网卡收发数据,但那是因为只有这样一来才能穿越所有软件防火墙,也是不得已而为之.如果上层能完成的功能,没有人会自己写底层.
你丫少在那里吹,动不动就"驱动".记得还有个贴说检测HOOK,你也是在那里"用驱动".好像只要不懂的,就一句"驱动",全部解决.真是误导大众.而且开发程序,实在没有必要什么都扯到驱动,本身驱动也没啥丫神秘的.开发项目讲求的是效率,能在上层完成的,就不要在下层动手,除非你能保证你写的比微软的好.
一句话:你去驱动开发论坛问问,看谁同意用驱动收发处理数据比完成端口性能高.如果你驱动写的不好(因为所有数据包你都得分析,处理),反而拖慢上面的别的应用程序.
 
我更不同意jingtao关于驱动不稳定,驱动效率低的说法。至少本人所在的小公司写的网络方案在以色列,韩国,土耳其的政府网络中大量使用(土耳其政府去年有12万套的订单)。

用驱动来收发数据有效率上几个显而易见的好处:
1.减少了ring0和ring3切换的时间片处理。
2.跳过微软变态的SPI层(这里有大量的分层dll一遍遍的过滤数据包)。
3.跳过常见防火墙守护的TDI层,个人防火墙通常要加载上万个规则来过滤每个包。
4.驱动内核可以申请大量的未分页内存来发送和接收数据,不需要系统在大量的缺页中断中不断的加载磁盘数据到虚拟内存而消耗时间。
 
"我更不同意jingtao关于驱动不稳定,驱动效率低的说法。"请看清楚,我是说你写的不可能有微软的稳定和效率高.Windows本身TCP数据也需要经过驱动排序之类再传递给上层应用程序的.

1:你什么公司名称?网络方案有人写,但不是效率问题,而是出于本身容许连接数问题.
我公司写的联合国也在用,这个月有2千亿订单.牛谁都会吹,如果真的那么牛,我想中国做网络的公司那么多,真的有那么好的东西,不会没人听说过吧.真有那么好,应该很多人在使用了.

"1.减少了ring0和ring3切换的时间片处理。"
你能比WINDOWS处理的更好?操作系统都是人家写的,难道你的切换比人家的快?

"2.跳过微软变态的SPI层(这里有大量的分层dll一遍遍的过滤数据包)。"
SPI我也做过,费尔防火墙的代码前几年就研究透了.SPI一般只是提供给用户使用.也没有所谓的大量分层DLL,除非是你自己安装的DLL.


任何事情有利有弊,你列一下弊端再说吧.最明显的是,无论IIS,还是APCHE,都没有直接从驱动层来收发数据的.也没有见什么大型程序例如QQ服务器之类出于收发效率自己写驱动收发数据.我想,那么多大公司,不会没有一个人比你所谓小公司的人聪明吧.
 
jingtao 强! 敬仰
 
[:D]我不知道jingtao怎么这么激动,如果触发了老兄什么敏感的神经,在下给你道歉,呵呵。
 
~ ~ 强 贴 留 名 ~ ~
 
DFW好久没有这么精彩的辩论了,希望继续下去!
 
说的也太远了把.
 
不远,技术是需要争论并用数据来说明的。
 
如果只是收发大批量的数据是没有问题,但如果在后续的处理中有耗时的操作那是一定会导致效率的下降的。

爱元元的哥哥说得1比较支持,的确ring0与ring3的切换比较耗时,但4好像就不是驱动的优势了,在ring3中也可以申请不被交换出去的内存。总的来说 还是少使用驱动为好,毕竟没有微软那样的实力做全面测试,我想BUG是在所难免的。
 
有没有Delphi完成端口控件啊?我们有偿求购。
现在用IOCPBST质量太差了。
请联系yangyongl@21cn.com
QQ:47297
 
我能说什么呢?

灌点水吧:
我到现在不明白完成端口是不是不支持UDP模式的SOCKET,我做的UDP都是先申请一个收发缓存,然后用线程去读缓存数据->处理 如果客户端发送的数据包太多 也就是缓存满了 就丢弃了。当然 TCP模式的SOCKET是不会丢的。

再问各位高手一个问题:
如果你有1万个用户,而你必须采用UDP模式进行通信,比如QQ。那么在服务端应该如何设置比较合理。

最后留个名吧:
期待高手的指点 qq:27885780 MSN:xiaokexinger@hotmail.com
 
难得赶上一次这么精采的辨论。
 
哈,元元和经淘的争辩,难得,留名先~~~
其实用驱动的问题,前几年我也研究过一点,感觉不是功底比较深的还是老实点的好,不过元元兄是大富翁的牛人,应该问题不大的
 
完成端口模型和常用的多线程模型不同
常用的多线程处理是对每一个请求创建一个线程处理请求的内容并将结果返回
而完成端口模型基本由三个线程处理请求
1监听线程 用于接受请求,并将请求内容保存到请求队列中
2处理线程 用于处理请求队列中的请求信息 根据请求的内容生成处理结果,并将结果放到返回队列
3返回线程, 将处理结果反馈给请求者

完成端口模型在大量请求的情况下体现出高性能的原因是线程数少,
用传统的阻塞或非阻塞的多线程处理,请求数达到500时线程数就达到500
这时系统要将大量的开销用于处理线程的调度(包括线程状态的保存和按优先级调度线程等).
这时的系统性能会迅速下降.
而完成端口模型在多请求任何情况下线程数不变(至少不会达到让系统开销大量增加的数量上)
所以在处理大量请求时完成端口模型具有很好的性能
 
比较支持jintao,尤其是现在的服务器级的网卡慢慢的开始带有数据校验,数块拆分重组,零拷贝,中断合并等硬件加速技术(这些都由硬件厂商做好了,现在的高级服务级网卡都不小的硬件buffer了),没必要自己写驱动而放弃了硬件更新带来的能力和系统的可靠性稳定性。当然针对具体业务的特殊情况是可以用自己做的驱动和协议提高速度(毕竟目前的协议中是考虑到了各种广泛的网络应用环境的),但是在保持同样的可通用,可伸缩前提下,我想ms在底层优化上也不能说是吃素的,要做的比ms有稍微明显的改善也是不太可信的。
 
抢个位置听课
 
不太同意GGCAT的说法:

微软的网络实现遵循ISO 7层构架,微软的驱动内核也采用分层构架,我们这些程序员大量写的驱动都是过滤性驱动,并不是实现型驱动,而且写过滤性驱动,并不是非常的难,只要搞懂微软那些DDK里面提供数以千计的函数。微软泄露了NT和2000的代码,因此这些函数认真学下来也不再难了。

比如防火墙驱动,并不是要代替ISO7层中的某一层,而是按照微软提供的标准方法,为某一层做过滤性挂接,从而实现包过滤的效果,这个类似Win32常用API Hook,微软也有API Hook的SDK-detours。微软为SPI,TDI,NDIS都提供了标准的过滤接口,你所做的工作就是在某个接口作逻辑判断,根本不会影响到系统的稳定性,微软设计驱动的分层构架就是为了补充其系统的功能,丰富更多的应用,微软也经常为系统打补丁,这就是分层构架的好处。在驱动里面处理网络连接算是比较简单的,和win32层的send,recv,shudown函数一样,在网络层,传输层,都有这样的函数,因此像很多网络安全系统,数据包走到链路层就开始分拣和处理了,大家可以参考libnet这个经典的例子。

Linux内核提供的Http服务器TUX,完全工作在Kernel mode,也就是工作在驱动层的Http服务器,工作效率高的惊人,这是学习linux网络内核很棒的案例。

又比如文件过滤驱动,其实它没有实现真正的文件系统,也是微软提供的标准过滤接口。文件的打开,创建,读写,关闭,都有相应的派发例程,你在这些例程里面要做的也很简单,过滤IRP,拦截IRP,修改IRP,或者什么都不作就往下传,这些都只是调用相应DDK里面的函数。大多数杀毒软件,加密软件,其实都在这一层工作。熟悉驱动开发的,只要看了微软DDK提供的Sfilter例子,都可以写一个基本的文件过滤驱动,其实编译一下就可以了,也可以学习FileMon的源码。比如:3721为什么总是杀不掉,就是使用了文件过滤引擎在自我保护。

除了那些硬件开发的,很少人在写实现型的驱动,大部分人都采用和微软提供的标准接口,在微软的Windows内核上加上一个Filter,这样就诞生了目前这么多的应用,虚拟盘,杀毒软件,透明加密解密,系统还原,防火墙,入侵检测,ISCSI,还原精灵等等。

学习TCP/ip可以借助一个小模型,Wattcp,这是一个在网卡包驱动基础上的一个非常经典的网络协议栈。Win2000的源代码里面也包含了整个TCP/IP的全部实现,不过比起linux的网络构架,它逊色了很多,这点大家可以看看Linux Netfilter的实现,真的是太漂亮了。
 
后退
顶部