计算机网络编程 | 多路I/O转接服务器

2024-07-19 1201阅读

计算机网络编程 | 多路I/O转接服务器

欢迎关注博主 Mindtechnist 或加入【Linux C/C++/Python社区】一起学习和分享Linux、C、C++、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学习,人工智能等相关领域的知识和技术。


多路I/O转接服务器

    • select
    • poll
    • epoll

      专栏:《网络编程》


      多路IO转接服务器也叫做多任务IO服务器。该类服务器实现的主旨思想是,不再由应用程序自己监视客户端连接,取而代之由内核替应用程序监视文件。

      主要使用的方法有三种,下面一一介绍并给出代码实现。

      select

      • select能监听的文件描述符个数受限于FD_SETSIZE,一般为1024,单纯改变进程打开的文件描述符个数并不能改变select监听文件个数。
      • 解决1024以下客户端时使用select是很合适的,但如果链接客户端过多,select采用的是轮询模型,会大大降低服务器响应效率,不应在select上投入更多精力。
        #include 
        /* According to earlier standards */
        #include 
        #include 
        #include 
        int select(int nfds, fd_set *readfds, fd_set *writefds,
        			fd_set *exceptfds, struct timeval *timeout);
        

        nfds: 监控的文件描述符集里最大文件描述符加1,因为此参数会告诉内核检测前多少个文件描述符的状态

        readfds: 监控有读数据到达文件描述符集合,传入传出参数

        writefds: 监控写数据到达文件描述符集合,传入传出参数

        exceptfds: 监控异常发生达文件描述符集合,如带外数据到达异常,传入传出参数

        timeout: 定时阻塞监控时间,3种情况

        ①NULL,永远等下去

        ②设置timeval,等待固定时间

        ③设置timeval里时间均为0,检查描述字后立即返回,轮询

        	struct timeval {
        		long tv_sec; /* seconds */
        		long tv_usec; /* microseconds */
        	};
        	void FD_CLR(int fd, fd_set *set); 	//把文件描述符集合里fd清0
        	int FD_ISSET(int fd, fd_set *set); 	//测试文件描述符集合里fd是否置1
        	void FD_SET(int fd, fd_set *set); 	//把文件描述符集合里fd位置1
        	void FD_ZERO(fd_set *set); 			//把文件描述符集合里所有位清0
        

        server实现

        /* server.c */
        #include 
        #include 
        #include 
        #include 
        #include 
        #include "wrap.h"
        #define MAXLINE 80
        #define SERV_PORT 6666
        int main(int argc, char *argv[])
        {
        	int i, maxi, maxfd, listenfd, connfd, sockfd;
        	int nready, client[FD_SETSIZE]; 	/* FD_SETSIZE 默认为 1024 */
        	ssize_t n;
        	fd_set rset, allset;
        	char buf[MAXLINE];
        	char str[INET_ADDRSTRLEN]; 			/* #define INET_ADDRSTRLEN 16 */
        	socklen_t cliaddr_len;
        	struct sockaddr_in cliaddr, servaddr;
        	listenfd = Socket(AF_INET, SOCK_STREAM, 0);
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port = htons(SERV_PORT);
        Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
        Listen(listenfd, 20); 		/* 默认最大128 */
        maxfd = listenfd; 			/* 初始化 */
        maxi = -1;					/* client[]的下标 */
        for (i = 0; i  maxfd)
        			maxfd = connfd; 		/* select第一个参数需要 */
        		if (i > maxi)
        			maxi = i; 				/* 更新client[]最大下标值 */
        		if (--nready == 0)
        			continue; 				/* 如果没有更多的就绪文件描述符继续回到上面select阻塞监听,
        										负责处理未处理完的就绪文件描述符 */
        		}
        		for (i = 0; i  	/* 检测哪个clients 有数据就绪 */
        			if ( (sockfd = client[i])  0:等待指定毫秒数,如当前系统时间精度不够毫秒,向上取值。 
         
        

        如果不再监控某个文件描述符时,可以把pollfd中,fd设置为-1,poll不再监控此pollfd,下次返回时,把revents设置为0。

        server实现

        /* server.c */
        #include 
        #include 
        #include 
        #include 
        #include 
        #include 
        #include 
        #include "wrap.h"
        #define MAXLINE 80
        #define SERV_PORT 6666
        #define OPEN_MAX 1024
        int main(int argc, char *argv[])
        {
        	int i, j, maxi, listenfd, connfd, sockfd;
        	int nready;
        	ssize_t n;
        	char buf[MAXLINE], str[INET_ADDRSTRLEN];
        	socklen_t clilen;
        	struct pollfd client[OPEN_MAX];
        	struct sockaddr_in cliaddr, servaddr;
        	listenfd = Socket(AF_INET, SOCK_STREAM, 0);
        	bzero(&servaddr, sizeof(servaddr));
        	servaddr.sin_family = AF_INET;
        	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        	servaddr.sin_port = htons(SERV_PORT);
        	Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
        	Listen(listenfd, 20);
        	client[0].fd = listenfd;
        	client[0].events = POLLRDNORM; 					/* listenfd监听普通读事件 */
        	for (i = 1; i  maxi)
        				maxi = i; 						/* 更新client[]中最大元素下标 */
        			if (--nready  			/* 检测client[] */
        			if ((sockfd = client[i].fd) 
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]