网络编程学习:io模型之io多路复用
2017-11-09 15:25
645 查看
多路复用的概念:
简而言之,就是将准备要用的文件描述符添加到一张表里,然后让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, cl 4000 iaddr; socklen_t addrlen = sizeof(struct sockaddr_in); char buf ; 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; }
相关文章推荐
- UNIX环境高级编程学习之第十六章网络IPC:套接字 - 非阻塞的Socket通信Poll模型(多路复用), 实用Socket通信模板
- UNIX环境高级编程学习之第十六章网络IPC:套接字 - 非阻塞的Socket通信EPoll模型(多路复用), 实用Socket通信模板
- 网络编程IO模型--学习笔记
- 关于重叠IO网络编程模型的学习!
- UNIX环境高级编程学习之第十六章网络IPC:套接字 - 非阻塞的Socket通信Select模型(多路复用), 实用Socket通信模板。
- JAVA网络编程基础知识-Linux网络IO模型
- 网络编程学习总结(之client/server模型)
- 网络编程中的5种IO模型
- Java IO、网络编程、NIO、Netty、Hessian、RPC、RMI的学习路线
- 网络编程五种IO模型之重叠IO模型-完成例程
- 网络编程的5个io模型
- linux网络编程之IO模型
- 网络编程--IO模型示例
- Python socket编程之IO模型介绍(多路复用*)
- 网络编程--IO模型示例
- 【Linux网络编程】深入理解Linux五种网络IO模型
- (转)linux网络编程之IO模型
- netty学习(一)--linux下的网络io模型简介
- Linux网络通信编程(套接字模型TCP\UDP与IO多路复用模型select\poll\epoll)
- 关于网络编程五种IO模型的形象比喻