C++ 对于多个同时连接,我应该使用什么基于套接字的模型?

C++ 对于多个同时连接,我应该使用什么基于套接字的模型?,c++,sockets,simultaneous,c10k,C++,Sockets,Simultaneous,C10k,我需要知道什么样的基于套接字的模型最适合同时连接多个服务器,就像在MMORPG服务器中一样 我读过关于c10k的文章,但是如果我的服务器一次只允许5000个客户端,我应该使用什么呢?阻塞套接字,线程化(每个客户端一个线程)?非阻塞插座,非螺纹?只在几个线程中处理所有客户端的循环?IOCP 简言之,优点和缺点是什么?我已经在谷歌上搜索过了,但是我没有找到一篇关于所有这些模型的具体的“对”文章 还是有更简单的方法来处理c10k问题 平台:WindowsXP你读过这篇文章吗 我做了类似的研究,找到了图

我需要知道什么样的基于套接字的模型最适合同时连接多个服务器,就像在MMORPG服务器中一样

我读过关于c10k的文章,但是如果我的服务器一次只允许5000个客户端,我应该使用什么呢?阻塞套接字,线程化(每个客户端一个线程)?非阻塞插座,非螺纹?只在几个线程中处理所有客户端的循环?IOCP

简言之,优点和缺点是什么?我已经在谷歌上搜索过了,但是我没有找到一篇关于所有这些模型的具体的“对”文章

还是有更简单的方法来处理c10k问题

平台:WindowsXP你读过这篇文章吗


我做了类似的研究,找到了图书馆。我相信它使用Select()而不是任何较新的方法,但是有许多用户表示他们已经使用它取得了很好的效果。如果您确实需要这么多的同时连接,则不难进行更改。

与服务器交互的方式在很大程度上取决于客户端如何发送数据、发送的数据类型、预期传输速率和流量模式

例如,如果你正在编写一个游戏,允许人们在虚拟礼堂里一起玩音乐,那么你基本上是在做大量的流媒体

如果你有一个多玩家的pacman,那么当方向改变时,你可以发送小数据包,所以它不是恒定的,而是突发的

然后,您可以决定是否必须保证数据包顺序,以及发送的每个数据包的重要性,因为您需要查看TPC或UDP。()

如果您想支持5000个客户端,那么拥有那么多的线程可能会是一个性能问题,这取决于内存的多少,但更重要的是,您拥有多少内核以及处理的cpu密集度,但它很可能会成为性能杀手

然后您可以查看
select()
(),这将允许较少的线程来处理负载,但是,如果您是流式处理,那么这可能是一个问题,因为专用线程更有意义


因此,如何决定哪种游戏是最好的取决于您正在编写的游戏类型,因为这两种类型都可能有用,具体取决于场景。

我个人建议您使用基于IOCP的设计,但我要说的是,我多年来一直在为客户开发高性能服务器

我最近总结了我喜欢IOCP而不是windows上其他型号的一些原因,这些都可以在我的博客上找到

通常,“复杂性”被认为是避免IOCP的一个原因,但是,老实说,如果你做的不是“每连接一个线程”,那么代码无论如何都会相当复杂。我有一个你可以看看的例子,它为你做了所有的IOCP工作,服务器示例是你自己代码的一个很好的起点。你可以从我这里得到它

另外,我还有一个免费的(非商业用途)可插拔服务器平台,您可能会感兴趣。使用WASP,您只需编写一个带有特定入口点的dll,我就可以为您完成所有的网络工作。。。有关下载和教程,请参见

无论您选择哪种型号,最重要的事情是IMHO,都是从第0天开始进行性能和负载测试。通过这种方式,您可以知道在目标硬件上可以支持多少并发连接,并且可以快速发现导致连接中断的不适当的设计决策。很容易浪费服务器的并发性。有关更多信息,请参阅


自从Jay提到ENet。。。我发现我们基于IOCP的ENet服务器与标准的ENet客户端代码配合得很好。但请记住,ENet是为对等协议而设计的,因此当您开始尝试在服务器上使用它时,会遇到一些挑战。使用标准的ENet代码,您基本上拥有一个单线程网络泵,这无法与您从IOCP获得的可伸缩性相比。最后,我从头开始重写了ENet协议处理代码,以使用异步I/O和IOCP,这是一项非常艰巨的工作。我目前正在编写一个新版本的代码,它使用最新的ENet协议作为基础,希望在2011年初可以使用,并与大量并发连接服务器情况下使用的标准ENet代码进行性能比较。

您应该使用IOCP和套接字I/O(任何简单的I/O)使用ReadFile和WriteFile

您的代码应该专注于等待I/O完成、加载完成的上下文、处理并最终生成新的I/O,您可以等待其完成

您的服务代码(我认为在使用C的上下文中)应该是多线程的,但线程数不应超过核心数


I/O完成端口的成本几乎为零,只有几个线程也是如此。因此,如果您能够足够快地完成您的任务,那么NT引擎可以处理的I/O完成量实际上是没有限制的。您的internet连接可能会首先饱和。

请注意:如果您仍要将括号内的准标记添加为标记,则在问题标题中添加这些标记没有什么意义。请参阅等待I/O完成时有一个超时参数。当您超时(即服务没有完成)时,您可以运行活动会话/连接并进行内务管理,例如关闭在一定时间内没有响应的会话。如果您预见到超时不会发生,因为永远不会有空闲时间,那么您可以创建一个非常小的线程,它可能每秒唤醒一次,并发送一个虚拟I/O完成信号时间来执行内务管理。一个很少执行操作的线程将不会对整体性能产生影响。当您使用selects时,实际上是在轮询套接字。一个线程是否可以选择并不重要