网络编程学习:io模型之io多路复用

来源:互联网 发布:网络小说排行 知乎 编辑:程序博客网 时间:2024/04/24 21:29

多路复用的概念:

简而言之,就是将准备要用的文件描述符添加到一张表里,然后让select等待表里的任一描述符准备就绪(就是可以执行了),然后执行那个已经准备就绪的文件描述符,然后把其他的没有准备好的文件描述符全都删除;

援引知乎上的一个解释:

这些名词比较绕口,理解涵义就好。一个epoll场景:一个酒吧服务员(一个线程),前面趴了一群醉汉,突然一个吼一声“倒酒”(事件),你小跑过去给他倒一杯,然后随他去吧,突然又一个要倒酒,你又过去倒上,就这样一个服务员服务好多人,有时没人喝酒,服务员处于空闲状态,可以干点别的玩玩手机。至于epoll与select,poll的区别在于后两者的场景中醉汉不说话,你要挨个问要不要酒,没时间玩手机了。io多路复用大概就是指这几个醉汉共用一个服务员。
作者:匿名用户链接:https://www.zhihu.com/question/32163005/answer/55687802
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

io多路复用函数

int select(int maxfdpl, fd_set *readset, fd_set *writeset, fd_set exceptset, const struct timeval *timeout);
功能:允许一个进程去操作多个文件描述符,阻塞等待一个或多个文件描述符就绪,当有一个或者多个文件描述符准备就绪,则函数立即返回;

参数:
maxfdpl:指定待测试的描述符个数,它的值是描述符集合中最大值加1(因为描述符是从0开始的,例如:集合里有{0,1,2,3,4},此时描述符的个数为5(即最大值4加1));
readset:读文件描述符集合;
writeset:写文件描述法集合;
exceptset:异常条件的描述符集合;
timeout:它告知内核等待所指定的描述符中的任何一个多长时间,即用作超时检测;

返回值:
成功:
如果timeout == NULL,则返回准备就绪的文件描述的个数;
如果timeout != NULL,超时后返回0;
失败:
返回-1;

多路复用实例(让标准输入和accept同时可以被操作)

服务器端#include "select.h"int main(int argc, const char *argv[]){       int listenfd, connfd;    struct sockaddr_in servaddr, cliaddr;    socklen_t addrlen = sizeof(struct sockaddr_in);    char buf[N];    if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)    {        errlog("socket error");    }    servaddr.sin_family = AF_INET;    servaddr.sin_port = htons(atoi(argv[2]));    if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)    {        errlog("inet_pton error");    }    if(bind(listenfd, (struct sockaddr *)&servaddr, addrlen) < 0)    {        errlog("bind error");    }    if(listen(listenfd, LISTENQ) < 0)    {        errlog("listen error");    }    int maxfd;    fd_set readfds, middlefds;    //清空集合    FD_ZERO(&readfds);    maxfd = listenfd;    while(1)    {        //将标准输入和接收客户端连接加入到集合中        FD_SET(0, &readfds);        FD_SET(listenfd, &readfds);        //阻塞检测&readfds中哪个文件描述符准备好了,如果准备好了,就不再阻塞给下边的代码放行,同时清空那些没有准备好的文件描述符;        if(select(maxfd + 1, &readfds, NULL, NULL, NULL) < 0)        {            errlog("select error");        }        //检测readfds集合中0号文件描述符准备好了没有,准备好了的话则返回1;        if(FD_ISSET(0, &readfds))        {            fgets(buf, N, stdin);            fputs(buf, stdout);        }        if(FD_ISSET(listenfd, &readfds))        {            if( (connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &addrlen)) < 0)            {                errlog("accept error");            }            printf("%s--%d is coming\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));        }    }    close(listenfd);    close(connfd);    return 0;}
阅读全文
0 0
原创粉丝点击