关于使用完成端口的高并发SOCKET编程问题,请高手指教

daiwoo_wang 2016-04-20 05:31:49
最近因为工作需要,搜到了一篇CSDN上关于使用完成端口的高性能并发SOCKET编程文章,与工作相似的是,我确实需要处理大量客户端长链接的问题,一般来说一个客户端链接后会长期在线。我一直没做压力测试,不知道在大量客户端(5000个客户端是我的设计目标)申请连接时,是否可以链接以及连接后是否可以正常工作。而这个完成端口早就听说了,据说是专为解决大量并发而产生的。然而根据我初步阅读其代码,发现核心思想貌似是使用异步连接和信号量技术来处理来自客户端的链接。我首先想请教用过完成端口的达人,在完成端口技术中,如果同时维持5000个客户端在线,服务器是否实实在在的开销了5000个SOCKET。
其次,当服务器真的链接5000个客户端并实实在在的开销了5000个SOCKET时(或者若干SOCKET),如何计算每个SOCKET获得的理论带宽(以千兆网卡为例)。这与不使用完成端口技术获得5000个客户连接(假如可以的话)相比,在网络带宽上是否有优势?如果用异步的BeginAccept加上内存映射表和多线程技术来处理多客户端链接,与用完成端口技术来实现,到底有多大的差异呢?
由于还没有搞清楚完成端口的原来和使用流程,在这里把我的大概处理方法说明如下,注意这是没有经过压力测试的,我还真不知道5000个(或者1000个)客户端申请连接会是什么效果:
1. 程序主进程开启LISTEN
Server.Listen(5000);
注意,这个 Listen(5000)同样出现在了上文提到的完成端口技术的博文中,大家可以看他的代码
2. //** 启动接收监听线程
td = new Thread(new ThreadStart(DoListen));
td.Start();
3. 线程启动函数中这样处理:
Server.BeginAccept(new AsyncCallback(MyAccept), null);
4. 一旦有客户端连接请求,则回调函数 MyAccept中创建客户端线程
//** 在原始套接字上调用EndAccept返回新的套接字
Socket client = Server.EndAccept(iar);
//** 收到连接,查IP表,如果已有连接,则断掉以前的,然后重新创建
IPEndPoint clientpoint = client.RemoteEndPoint as IPEndPoint;

其中关键就是非阻塞方式调用BeginAccept和在原始SOCKET上用EndAccept去生成新的SOCKET,这个SOCKET被分配给客户端连接并会在一个记录客户端IP和SOCKET的映射表中得到反映。以后一旦有发送数据的需求,则根据客户端的IP查找对应的SOCKET。
到了这里,我最疑惑的问题就是上面提到的,当5000个客户端链接请求时,使用完成端口技术的方法是否和我这个方法一样,让服务器实实在在的付出了5000个SOCKET的代价,如果真是这样,那完成端口的优势在哪里?
顺便说一下,我的程序指导思想也是异步全双工处理客户端链接,上下(收发)由2个线程处理,走同一个SOCKET(一个客户端一个SOCKET)
...全文
2187 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
kakabulusi 2017-06-08
  • 打赏
  • 举报
回复
5000客户端的情况只有使用CS架构了, BS做这种应用,要么卡死,要么需要N台服务器做压力分流。
???387 2017-06-07
  • 打赏
  • 举报
回复
如果你会c# 用supersocket吧,人都封装好了,基于完成端口的,开源的, 如果你要自己处理,我只弄过2000人在线的,开始用的阻塞多线程模式,后来重构为完成端口,各有优劣,前者逻辑清晰,用法简单易于维护,后者开销小很多,其他的么有多大区别。我用的1万多一点的dell服务器,win2003 两种模式下都运行稳定。不过现在已经全部用完成端口了,开销小,服务器可以上虚拟机,一机多用
shenyi0106 2016-07-05
  • 打赏
  • 举报
回复
IOCP的高效主要来自于 最大程度的避免线程切换和ring0到ring3的切换。 在一个高并发的环境中,这两种切换将花费巨大的CPU时间。
公共马甲0315 2016-07-05
  • 打赏
  • 举报
回复
已经看了n遍所谓的IOCP的例程,没发现什么高明之处,只不过listen thread是由n个线程来执行罢了,其它的长连接的客户端通讯,不过是n个线程来回切换,但本质上,同一瞬间通讯的客户端还是一个子线程来完成了。不过比非阻塞多线程方式多了一个优势,就是它可以同一瞬间接收n个请求连接,非阻塞多线程方式因为只有一个listen子线程,所以当处理一个连接请求时,因为函数体没有执行完,所以其他的请求就得等一下。 如果楼主需要解决的不是大量客户端并发连入的情形,而只是并发数据通讯的话,建议直接多线程非阻塞模式,非阻塞模式recv耗时非常短。而且可以将缓存池固化,事先就分配好,不需要那种iocp不断动态分配方式,避免产生碎片。
转角天边 2016-06-27
  • 打赏
  • 举报
回复
1、5000个套接字是少不了的,会比5000还要多一些(监听套接字,还有投递给acceptex的套接字) 2、你说的那种不就是最基本的one thread per client吗,5000个客户端就要创建5000个线程,还是连接的时候创建的,而且客户端线程里面处理I/O请求又要用线程吧,具体还有什么优势,自己体会吧
xian_wwq 2016-04-22
  • 打赏
  • 举报
回复
IOCP要同时维持5000并发,那5000个socket肯定是少不了的 因为要接入一路,就要先创建个新的socket投递出去(AcceptEx模式) 看lz摘抄的代码,,貌似是c#的,在.net上使用iocp,不像c直接调用win api那么麻烦, 没必要自行处理好多细节 http://msdn.microsoft.com/zh-cn/magazine/cc163356.aspx 看看 SocketAsyncEventArgs 的论述

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧