我需要知道哪种基于套接字的模型最适合具有多个同时连接的服务器,就像在MMORPG服务器中一样。
我读过关于c10k的内容,但是我应该使用什么,例如我的服务器一次只允许5000个客户端?阻塞套接字,线程化(每个客户端一个线程)?非阻塞套接字,非线程?一个循环只处理几个线程中的所有客户端? IOCP?
简而言之,有哪些优点和缺点?我已经用谷歌搜索了,但我没有找到关于所有这些模型的具体“对比”文章。
或者有更简单的方法来处理c10k问题吗?
平台:Windows XP
答案 0 :(得分:4)
就我个人而言,我建议您使用基于IOCP的设计,但我会说,因为我已经使用an IOCP based framework多年来为客户开发高性能服务器。
我最近把我喜欢IOCP的一些理由放到了Windows上可用的其他模型上,它们可以在我的博客here上找到。
通常,“复杂性”被认为是避免IOCP的一个原因,但是,说实话,如果你正在做“每个连接的线程”以外的任何事情,那么代码将会相当复杂。我有一个free set of C++ code with example servers你可以看一下,它为你做了所有IOCP工作,服务器示例是你自己的代码的一个很好的起点。你可以从here获得它。
或者我也有一个免费(非商业用途)可插拔服务器平台,您可能会感兴趣。使用WASP,您只需编写带有一些特定入口点的dll,然后为您完成所有网络工作......请参阅here下载和here获取教程。
您决定使用哪一个最重要的模型,恕我直言,是从第0天开始执行您的性能和负载测试。这样您就知道您可以在目标硬件上支持多少并发连接,并且您可以快速发现不恰当的设计决定会导致这种情况下降。浪费服务器的并发性很容易。有关详细信息,请参阅here。
因为Jay提到了ENet ......我发现我们基于IOCP的ENet服务器与标准的Enet客户端代码配合得很好。但请记住,ENet旨在成为点对点协议,因此当您开始尝试在服务器上使用它时会遇到一些挑战。使用标准的ENet代码,您基本上只有一个单线程网络泵,而且无法与您从IOCP获得的可扩展性进行比较。我最终从头开始重写ENet协议处理代码以使用异步I / O和IOCP,这是一项非常重要的工作。我目前正在使用最新的ENet协议作为基础进行此代码的新版本,希望这将在2011年初提供,并与大量并发连接服务器情况下使用的标准ENet代码进行完整的性能比较。
答案 1 :(得分:1)
决定与服务器交互的方式在很大程度上取决于客户端如何发送数据,发送什么类型的数据,预期的传输速率和流量模式。
例如,如果您正在编写一款允许人们在虚拟礼堂聚会并播放音乐的游戏,那么您基本上就可以进行大量的流式传输。
如果你有一个多玩家pacman然后你可以发送小包,当方向改变时,所以它不会是常数,但是是突发性的。
然后您可以决定是否必须保证数据包顺序以及每个数据包发送的重要性,因为您需要查看TPC或UDP。(http://www.skullbox.net/tcpudp.php)
如果你想支持5000个客户端,那么拥有这么多线程可能是一个性能问题,具体取决于内存量,但更重要的是,你拥有多少内核以及处理的cpu密集程度,但是,几率是它将成为性能杀手。
然后你可以查看select()
(http://www.lowtek.com/sockets/select.html),这将允许较少数量的线程来处理负载,但是,如果你是流式传输,那么这可能是一个问题,作为专用线程更有意义。
那么,如何确定哪个最好取决于你正在编写什么类型的游戏,因为两者都有用,具体取决于场景。
答案 2 :(得分:0)
您是否阅读了this文章?
我做了类似的研究并找到了eNet库。我相信它使用Select()而不是任何更新的方法,但有许多用户表示他们已经有了非常好的结果。如果您绝对需要多个同时连接,那么改变并不困难。
答案 3 :(得分:0)
您应该使用ReadFile和WriteFile来使用IOCP和套接字I / O(任何简单的I / O)。
您的代码应该专注于等待I / O完成,加载完成的上下文,处理并最终生成可以等待完成的新I / O.
您的服务代码(我认为在使用C的上下文中)应该是多线程的,但没有比您拥有内核更多的线程。
I / O完成端口几乎没有成本,只有几个线程也是如此。因此,如果你能够足够快地完成比特,那么NT引擎可以处理的I / O完成次数确实没有限制。您的互联网连接可能会先饱和。