苏州网站开发公司兴田德润怎么联系,pc网页游戏网站,成都最新新闻事件今天,网站模板50元作者#xff1a;阿凡卢 出处#xff1a;http://www.cnblogs.com/luxiaoxun/服务器端几种模型#xff1a; 1、阻塞式模型#xff08;blocking IO#xff09; 我们第一次接触到的网络编程都是从 listen()、accpet()、send()、recv() 等接口开始的。使用这些接口可以很方便的…作者阿凡卢 出处http://www.cnblogs.com/luxiaoxun/ 服务器端几种模型 1、阻塞式模型blocking IO 我们第一次接触到的网络编程都是从 listen()、accpet()、send()、recv() 等接口开始的。使用这些接口可以很方便的构建C/S的模型。这里大部分的 socket 接口都是阻塞型的。所谓阻塞型接口是指系统调用一般是 IO 接口不返回调用结果并让当前线程一直阻塞只有当该系统调用获得结果或者超时出错时才返回。 如下面一个简单的Server端实现 View Code 示意图如下 这里的socket的接口是阻塞的blocking在线程被阻塞期间线程将无法执行任何运算或响应任何的网络请求这给多客户机、多业务逻辑的网络编程带来了挑战。 2、多线程的服务器模型Multi-Thread 应对多客户机的网络应用最简单的解决方式是在服务器端使用多线程或多进程。多线程或多进程的目的是让每个连接都拥有独立的线程或进程这样任何一个连接的阻塞都不会影响其他的连接。 多线程Server端的实现 View Code 上述多线程的服务器模型可以解决一些连接量不大的多客户端连接请求但是如果要同时响应成千上万路的连接请求则无论多线程还是多进程都会严重占据系统资源降低系统对外界响应效率。 在多线程的基础上可以考虑使用“线程池”或“连接池”“线程池”旨在减少创建和销毁线程的频率其维持一定合理数量的线程并让空闲的线程重新承担新的执行任务。“连接池”维持连接的缓存池尽量重用已有的连接、减少创建和关闭连接的频率。这两种技术都可以很好的降低系统开销都被广泛应用很多大型系统。 3、非阻塞式模型Non-blocking IO 非阻塞的接口相比于阻塞型接口的显著差异在于在被调用之后立即返回。 非阻塞型IO的示意图如下 从应用程序的角度来说blocking read 调用会延续很长时间。在内核执行读操作和其他工作时应用程序会被阻塞。 非阻塞的IO可能并不会立即满足需要应用程序调用许多次来等待操作完成。这可能效率不高因为在很多情况下当内核执行这个命令时应用程序必须要进行忙碌等待直到数据可用为止。 另一个问题在循环调用非阻塞IO的时候将大幅度占用CPU所以一般使用select等来检测”是否可以操作“。 4、多路复用IO 支持I/O复用的系统调用有select、poll、epoll、kqueue等 这里以Select函数为例select函数用于探测多个文件句柄的状态变化以下为一个使用了使用了Select函数的Server实现 View Code 示意图如下 这里Select监听的socket都是Non-blocking的所以在do_read() do_write()中对返回为EAGAIN/WSAEWOULDBLOCK都做了处理。 从代码中可以看出使用Select返回后仍然需要轮训再检测每个socket的状态读、写这样的轮训检测在大量连接下也是效率不高的。因为当需要探测的句柄值较大时select () 接口本身需要消耗大量时间去轮询各个句柄。 很多操作系统提供了更为高效的接口如 linux 提供 了 epollBSD 提供了 kqueueSolaris 提供了 /dev/poll …。如果需要实现更高效的服务器程序类似 epoll 这样的接口更被推荐。遗憾的是不同的操作系统特供的 epoll 接口有很大差异所以使用类似于 epoll 的接口实现具有较好跨平台能力的服务器会比较困难。 5、使用事件驱动库libevent的服务器模型 Libevent 是一种高性能事件循环/事件驱动库。 为了实际处理每个请求libevent 库提供一种事件机制它作为底层网络后端的包装器。事件系统让为连接添加处理函数变得非常简便同时降低了底层IO复杂性。这是 libevent 系统的核心。 创建 libevent 服务器的基本方法是注册当发生某一操作比如接受来自客户端的连接时应该执行的函数然后调用主事件循环 event_dispatch()。执行过程的控制现在由 libevent 系统处理。注册事件和将调用的函数之后事件系统开始自治在应用程序运行时可以在事件队列中添加注册或 删除取消注册事件。事件注册非常方便可以通过它添加新事件以处理新打开的连接从而构建灵活的网络处理系统。 使用Libevent实现的一个回显服务器如下 View Code 6、信号驱动IO模型Signal-driven IO 使用信号让内核在描述符就绪时发送SIGIO信号通知应用程序称这种模型为信号驱动式I/Osignal-driven I/O。 图示如下 首先开启套接字的信号驱动式I/O功能并通过sigaction系统调用安装一个信号处理函数。该系统调用将立即返回我们的进程继续工作也就是说进程没有被阻塞。当数据报准备好读取时内核就为该进程产生一个SIGIO信号。随后就可以在信号处理函数中调用recvfrom读取数据报并通知主循环数据已经准备好待处理也可以立即通知主循环让它读取数据报。 无论如何处理SIGIO信号这种模型的优势在于等待数据报到达期间进程不被阻塞。主循环可以继续执行 只要等到来自信号处理函数的通知既可以是数据已准备好被处理也可以是数据报已准备好被读取。 7、异步IO模型asynchronous IO 异步I/Oasynchronous I/O由POSIX规范定义。演变成当前POSIX规范的各种早起标准所定义的实时函数中存在的差异已经取得一致。一般地说这些函数的工作机制是告知内核启动某个操作并让内核在整个操作包括将数据从内核复制到我们自己的缓冲区完成后通知我们。这种模型与前一节介绍的信号驱动模型的主要区别在于信号驱动式I/O是由内核通知我们何时可以启动一个I/O操作而异步I/O模型是由内核通知我们I/O操作何时完成。 示意图如下 我们调用aio_read函数POSIX异步I/O函数以aio_或lio_开头给内核传递描述符、缓冲区指针、缓冲区大小与read相同的三个参数和文件偏移与lseek类似并告诉内核当整个操作完成时如何通知我们。该系统调用立即返回并且在等待I/O完成期间我们的进程不被阻塞。本例子中我们假设要求内核在操作完成时产生某个信号该信号直到数据已复制到应用进程缓冲区才产生这一点不同于信号驱动I/O模型。 参考 《UNIX网络编程》 使用 libevent 和 libev 提高网络应用性能http://www.ibm.com/developerworks/cn/aix/library/au-libev/ 使用异步 I/O 大大提高应用程序的性能https://www.ibm.com/developerworks/cn/linux/l-async/ 作者阿凡卢 出处http://www.cnblogs.com/luxiaoxun/ 本文版权归作者和博客园共有欢迎转载但未经作者同意必须保留此段声明且在文章页面明显位置给出原文连接否则保留追究法律责任的权利。 转载于:https://www.cnblogs.com/lizhanwu/articles/4169734.html