• 网络编程、poll轮询、select机制


    具体实现机制:
        1. select机制
            1) 函数接口:
            /* According to POSIX.1-2001 */
            #include
                    
            /* According to earlier standards */
            #include time.h>
            #include
            #include
                    
            int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
            参数:
                参数1:nfds表示的是集合中最大文件描述符+1;
                参数2:readfds表示关心的读事件集合,不关心用NULL填充
                参数3:writefds表示关心的写事件集合,不关心用NULL填充
                参数4:exceptfds表示关心的其它事件集合,不关心用NULL填充
                参数5:timeout用来设置阻塞事件
                      a, 设置为NULL,表示检测时一直阻塞,直到有事件准备就绪函数才返回
                      b, 设置结构体的值
                          struct timeval {
                            long    tv_sec;         /* seconds */
                            long    tv_usec;        /* microseconds */
                        };
                        1) 成员的值都0,非阻塞方式检测;
                        2) 成员值为非零,有阻塞时间。
            返回值:
                成功返回值准备就绪事件的个数;
                返回0表示检测超时
                失败返回-1,且修改errno的值。
                                
            void FD_CLR(int fd, fd_set *set);    /* 将文件描述符fd从集合set中移除 */
            int  FD_ISSET(int fd, fd_set *set);    /* 检测文件描述符fd是否在集合set,如果在返回非0,不在返回0 */
            void FD_SET(int fd, fd_set *set);    /* 将文件描述符fd添加到集合set中 */
            void FD_ZERO(fd_set *set);            /* 清空集合set */
                                
            2) 具体实现的思路:
                a,创建读事件集合readfds,并清空集合
                    fd_set readfds;
                    FD_ZERO(&readfds);
                                        
                b,将文件描述符listenfd添加到读事件集合readfds中;
                    FD_SET(listenfd, &readfds);
                                        
                c,检测集合中是否有准备就绪的事件(阻塞方式检测,有事件准备就绪函数返回)
                    ret = select(nfds, &readfds, NULL, NULL, NULL);
                                    
                d,得到准备就绪事件的文件描述符
                    for(fd = 0; fd < nfds; fd++) {
                        if (FD_ISSET(fd, &readfds)) {
                            e,对fd进IO操作。
                        }
                    }
            3) 特征:
                a,可以在一个任务中对多个阻塞io进程操作,谁先准备就绪,就操作谁。
                b,如果操作事件不同,需要定义多个集合;
                c,找到准备就绪的文件描述符的时候,需要从0遍历到最大的文件描述符。效率很低。    

       2. poll机制       

    相关函数接口:
                #include
                int poll(struct pollfd *fds, nfds_t nfds, int timeout);
                参数:
                    参数1:fds表示是IO操作的集合(数组)首元素的地址
                        struct pollfd {
                            int   fd;         /* file descriptor */
                            short events;     /* requested events */
                            short revents;    /* returned events */
                        };
                        events / revents:
                        POLLIN    :读事件;
                        POLLOUT    :写事件;        
                 参数2:nfds表示表示fds中的有效项数;
                 参数3:timeout表示事件检测时间(是以ms为单位)
                            如果timeout = -1,表示以阻塞的方式去检测,没有事件准备就绪就一直阻塞,直到有事件准备就绪才返回。
                            如果timeout > 0 阻塞时间为timeout
                            如果timeout = 0 非阻塞方式;

                2) poll机制的具体是实现流程:
                    a,创建集合,并清空集合
                        struct pollfd fds[1024];
                        memset(fds, 0, sizeof(fds));
                        for (i = 0; i < 1024; i++)
                            fds[i].fd = -1;
                    b,将文件描述符listenfd及其对应的读写事件(POLLIN、POLLOUT)添加到集合fds中;
                        fds[0].fd = listenfd;
                        fds[0].events = POLLIN | POLLOUT;
                        nfds = 1;
                    while(1) {
                        c,调用poll函数,检测是否有准备就绪的事件,如果没有事件准备就绪,函数一直阻塞。如果有事件准备就绪函数返回;
                        ret = poll(fds, nfds, -1);

                        d, 找到准备就绪事件的文件描述符;
                            for(i = 0; i < nfds; i++) {
                                if (fds[i].fd == -1) 
                                    continue;
                                fd = fds[i].fd;
                                if (fds[i].revents == POLLIN) {
                                    e,处理读事件,IO读操作
                                } else if (fds[i].revents == POLLOUT) {
                                    e,处理写事件,IO写操作
                                }
                            }
                    }

                    优缺点: 
                        1. 集合数减少,空间增大;
                        2. 效率提高;依然会对集合中所有元素进行遍历。(随着集合中元素的增多效率会下降)

  • 相关阅读:
    对透传 Attributes 的理解
    网路通信之校验和
    Qt鼠标跟踪
    本地离线模型搭建指南-中文大语言模型底座选择依据
    MySqL速成教程笔记系列九
    被邀请为期刊审稿时,如何做一个合格的审稿人?官方版本教程来喽
    【牛客网】安全—加密和安全
    #{} ${} 解析
    opencv学习笔记二——图像基本操作
    Unity_Demo | 中世纪风3D-RPG游戏
  • 原文地址:https://blog.csdn.net/qq_52119661/article/details/132747707