C10K--10000个客户端的诱惑

        如果不熟悉网络编程,建议先学习Linux的网络编程部分+signal模型(或者Windows的网络编程+Complete端口模型)。ACE是个不错的包,封装了这些模型,但是没有较好的理论基础,要设计高性能的网络服务器是不大可能的。
        网络服务器的几种模型可以参考 C10K的介绍。当然,如果在linux下,最好的模型自然是 EPoll(effective poll?)。目前一台服务器支持10K个客户访问,基本上还比较麻烦,64位的CPU,可能是一个比较好的解决方案。2块1000M网卡,10K客户端,每个客户端的带宽是2000/10000=200K,这是理论值,勉强可行。
        考虑一下纯粹的线程模型。10K个客户端,需要10K个线程。考虑到每个进程3G的用户空间,那么每个线程的空间是3000M/10K=300K,只能说非常勉强可以运行(每个线程的c runtime大约需要2-3K空间)。但是大量的线程调度会极大的减缓系统效率。
        再考虑一下多个进程的模型,每个进程创建多个线程。其实与纯粹的线程模型差异不大,不过是每个线程的用户空间不受太大限制。大量的线程调度带来的巨大性能损耗会使得整个系统效率及其低下。当然,这种模型也不是一无是处,对于客户端数目不多的情况,比如ftp服务器,这种模型是非常合适的。
        然后就剩下EPoll模型。要使用EPoll模型,首先必须有Linux2.6的内核。建议安装Fedora Core2。了解select模型的人都知道,select每个句柄只能支持64个socket,这可以通过阅读linux select.h知道。而Poll模型则是一种事件触发的模型,没有64个socket的限制。EPoll是对Poll模型的一个改造,让一个Poll句柄可以同时支持多个Socket句柄,好处是将大量Poll句柄的事件探测机制放到内核中处理,大大减少了将数据从内核态拷贝到用户态的次数,从而提高效率。阅读Linux的源码可以看到,EPoll的内部使用的是一个Hashmap,Hashmap中存放Poll对象,所以从根本上来说,EPoll模型是一种更好的Poll模型(我一直理解为Effective Poll)。
        观察Linux的源码可以看到,每次创建一个Socket句柄,都会有一个File对象被创建。对于C10K来说,意味着要创建10K个文件句柄。Linux系统上每个进程可以创建的文件句柄数目是有限制的,可以阅读Linux源码的struct Files结构看到,1024个。幸好Linux系统提供了扩展的办法。最为简单的做法是使用一个命令叫做ulimit,不过这个命令必须每次启动进程都做一次。另一个方法是修改源码,重新编译内核。这个办法比较实用,一劳永逸。
        

你可能感兴趣的:(c,linux,socket,网络,HashMap,FTP服务器)