行业知识
网络编程难点之select、poll与epoll详解
前言
为什么需要I/O多路复用技术?
首先,I/O多路复���技术主要被应用在需要高性能的网络服务器程序中。
高性能网络服务器程序需要做的事情就是供多个客户端同时进行连接并处理客户端传送过来的数据请求:
对于这种情况,很多人自然而然想到使用多线程的方式来处理,这当然是正确的想法,但这里我们并不讨论它,只探讨我们为什么需要I/O多路复用技术以及它到底能解决什么问题,因此多线程情况我们不作分析,下面都只探讨单线程情况下的程序情况。
在单线程情况下,多个客户端发起连接请求时,同一时间下服务器程序只能处理一个客户端的数据请求:
假设服务器程序接受了客户端1号的数据请求,那么单线程情况下该服务器程序就只能和客户端1号进行数据传输,此时若有客户端2号、3号发起连接请求,那么它们只能被阻塞(注意,后续客户端请求只是阻塞起来排起了队,并非数据就不要了,而这种技术是通过DMA控制器实现的,在计算机组成原理中有详细介绍这种技术)。
因此单线程服务器程序为了服务到位所有的客户端程序,我们理所当然的在写服务器端程序的数据处理代码时会有如下的逻辑:
//数据处理while(1){//Fdx是建立通信连接的文件描述符//FdA~FdE表示已经建立通信连接的文件描述符数组for(Fdx in (FdA~FdE)){if(Fdx 有数据){读数据;处理数据;}}} 即循环遍历各个已经建立通信连接的文件描述符,每遍历到一个就进行一次是否有数据的判断,然后进行数据处理。
这种方式简单粗暴,其实效率上也并不低,但是它确实有改进的地方,其缺陷如下:
1、时间复杂度高,很明显第二重循环是每次都要从头遍历的
2、每次都需要判断文件描述符中是否有数据,这个过程涉及到内核,用户态与内核态的频繁切换是其性能低下的原因之一
那么在单线程程序中,我们就可以使用I/O多路复用技术来提高单线程下在面对上述程序所面对的问题时的执行效率,也就是下面要说的select、poll和epoll技术(当然多线程下同样适用,但只要明白了单线程下的情况,多线程的情况也就是照猫画虎)。
select
首先来看一段代码,注意其中注释里的内容:
sockfd = socket(AF_INET, SOCK_STREAM, 0); memset(&addr, 0, sizeof (addr)); addr.sin_family = AF_INET; addr.sin_port = htons(2000); addr.sin_addr.s_addr = INADDR_ANY; bind(sockfd,(struct sockaddr*)&addr ,sizeof(addr)); listen (sockfd, 5); for (i=0;i memset(&client, 0, sizeof (client)); addrlen = sizeof(client); fds[i] = accept(sockfd,(struct sockaddr*)&client, &addrlen); if(fds[i] max) max = fds[i]; }// 上面是在准备下面代码要使用的已经建立通信连接的套接字文件描述符数组//----------------------------------------------------------------// 下面是处理连接请求的代码 while(1){FD_ZERO(&rset); for (i = 0; i
上一篇:服务器机柜怎么配置?