【转】阻塞与非阻塞socket的优缺点

转自:http://wenku.baidu.com/link?url=V-TghOmERC0eq0aoXEyhpTw3W5OlqbItwTJE_csI29ysi9vKkCG1lDxq0wWdpImvg3qFf1BKUrDEPUz-4uCbiROduS0EswpvmBvuzVfbtuO服务器

NIO 设计背后的基石:反应器模式,用于事件多路分离和分派的体系结构模式。 反应器(Reactor):用于事件多路分离和分派的体系结构模式
一般的,对一个文件描述符指定的文件或设备, 有两种工做方式: 阻塞与非阻塞 。所谓阻塞方式的意思是指,当试图对该文件描述符进行读写时,若是当时没有东西可读,或者暂时不可写,程序就进入等待状态,直到有东西可读或者可写为止。而对于非阻塞状态,若是没有东西可读,或者不可写,读写函数立刻返回,而不会等待。
一种经常使用作法是:每创建一个Socket链接时,同时建立一个新线程对该Socket进行单独通讯(采用阻塞的方式通讯)。这种方式具备很高的响应速度,而且控制起来也很简单,在链接数较少的时候很是有效,可是若是对每个链接都产生一个线程的无疑是对系统资源的一种浪费,若是链接数较多将会出现资源不足的状况。
另外一种较高效的作法是:服务器端保存一个Socket链接列表,而后对这个列表进行轮询,若是发现某个Socket端口上有数据可读时(读就绪),则调用该socket链接的相应读操做;若是发现某个 Socket端口上有数据可写时(写就绪),则调用该socket链接的相应写操做;若是某个端口的Socket链接已经中断,则调用相应的析构方法关闭该端口。这样能充分利用服务器资源,效率获得了很大提升。
传统的阻塞式IO,每一个链接必需要开一个线程来处理,而且没处理完线程不能退出。
非阻塞式IO,因为基于反应器模式,用于事件多路分离和分派的体系结构模式,因此能够利用线程池来处理。事件来了就处理,处理完了就把线程归还。而传统阻塞方式不能使用线程池来处理,假设当前有10000个链接,非阻塞方式可能用1000个线程的线程池就搞定了,而传统阻塞方式就须要开10000个来处理。若是链接数较多将会出现资源不足的状况。非阻塞的核心优点就在这里。
为何会这样,下面就对他们作进一步细致具体的分析:
首先,咱们来分析传统阻塞式IO的瓶颈在哪里。在链接数很少的状况下,传统IO编写容易方便使用。可是随着链接数的增多,问题传统IO就不行了。由于前面说过,传统IO处理每一个链接都要消耗一个线程,而程序的效率当线程数很少时是随着线程数的增长而增长,可是到必定的数量以后,是随着线程数的增长而减小。这里咱们得出结论,传统阻塞式IO的瓶颈在于不能处理过多的链接。
而后,非阻塞式IO的出现的目的就是为了解决这个瓶颈。而非阻塞式IO是怎么实现的呢?非阻塞IO处理链接的线程数和链接数没有联系,也就是说处理10000个链接非阻塞IO不须要10000个线程,你能够用1000个也能够用2000个线程来处理。由于非阻塞IO处理链接是异步的。当某个链接发送请求到服务器,服务器把这个链接请求看成一个请求"事件",并把这个"事件"分配给相应的函数处理。咱们能够把这个处理函数放到线程中去执行,执行完就把线程归还。这样一个线程就能够异步的处理多个事件。而阻塞式IO的线程的大部分时间都浪费在等待请求上了。异步

相关文章
相关标签/搜索