IO复用:Poll

Poll

和select 一样.如果没有事件发生.则进入休眠状态.如果在规定时间内有事件发生.则返回成功.规定时间过后仍然没有事件发生则返回失败.可见.等待期间将进程休眠.利用事件驱动来唤醒进程.将更能提高CPU的效率.

接口

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

输入参数:
fds://可以传递多个结构体,也就是说可以监测多个驱动设备所产生的事件,只要有一个产生了请求事件,就能立即返回
struct pollfd {
int fd; /文件描述符 open打开的那个/
short events; /请求的事件类型,监视驱动文件的事件掩码
short revents; /驱动文件实际返回的事件/
}
nfds: //监测驱动文件的个数
timeout://超时时间,单位是ms

事件类型events 可以为下列值:
POLLIN 有数据可读
POLLRDNORM 有普通数据可读,等效与POLLIN
POLLPRI 有紧迫数据可读
POLLOUT 写数据不会导致阻塞
POLLER 指定的文件描述符发生错误
POLLHUP 指定的文件描述符挂起事件
POLLNVAL 无效的请求,打不开指定的文件描述符

返回值: 有事件发生 返回revents域不为0的文件描述符个数
超时:return 0
失败:return -1 错误:errno
Poll_demo

#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
#include <poll.h>

#define SERVER_IP "127.0.0.1"
#define MAX_FD  8192
struct pollfd  fds[MAX_FD];
int cur_max_fd = 0;

void set_Maxfd(int fd){
    
    
     if(cur_max_fd <= fd)
    {
    
    
        cur_max_fd = fd + 1;
    }
}
int main()
{
    
    
    int server_sockfd, client_sockfd;
    int server_len, client_len;
    struct sockaddr_in server_address;
    struct sockaddr_in client_address;
    int result;
    //fd_set readfds, testfds;
    server_sockfd = socket(AF_INET, SOCK_STREAM, 0);//建立服务器端socket
    server_address.sin_family = AF_INET;
    /*server_address.sin_addr.s_addr = htonl(INADDR_ANY);*/
    server_address.sin_addr.s_addr=inet_addr(SERVER_IP);
    server_address.sin_port = htons(9000);
    server_len = sizeof(server_address);
    bind(server_sockfd, (struct sockaddr*)&server_address, server_len);
    listen(server_sockfd, 5); //监听队列最多容纳5个
    //FD_ZERO(&readfds);
    //FD_SET(server_sockfd, &readfds);//将服务器端socket加入到集合中
    fds[server_sockfd].fd = server_sockfd;
    fds[server_sockfd].events = POLLIN;
    fds[server_sockfd].revents = 0;
    set_Maxfd(server_sockfd);
    while (1)
    {
    
    
        char buff[256],send_buff[256];
        int i, fd;
        int nread;
        printf("server waiting\n");
        /*无限期阻塞,并测试文件描述符变动 */
        result = poll(fds, cur_max_fd, 1000);
        //result = select(FD_SETSIZE, &testfds, (fd_set*)0, (fd_set*)0, (struct timeval*)0); //FD_SETSIZE:系统默认的最大文件描述符
        if (result < 0)
        {
    
    
            perror("server5");
            exit(1);

        }
        
        /*扫描所有的文件描述符*/
        for (i = 0; i < cur_max_fd; i++)
        {
    
    

            /*找到相关文件描述符*/
            if (fds[i].revents)
            {
    
    
                fd = fds[i].fd;
                /*判断是否为服务器套接字,是则表示为客户请求连接。*/
                if (fd == server_sockfd)
                {
    
    
                    client_len = sizeof(client_address);
                    client_sockfd = accept(server_sockfd,
                        (struct sockaddr*)&client_address, &client_len);
                    fds[client_sockfd].fd = client_sockfd;//将客户端socket加入到集合中
                    fds[client_sockfd].events = POLLIN;
                    fds[client_sockfd].revents = 0;
                    set_Maxfd(client_sockfd);
                    printf("adding client on fd %d\n", client_sockfd);
                    //fds[server_sockfd].events = POLLIN;
                }
                /*客户端socket中有数据请求时*/
                else
                {
    
    
                    if(fds[i].events&POLLIN){
    
    
                        //ioctl(fd, FIONREAD, &nread);//取得数据量交给nread
                        nread = read(fd, buff, sizeof(buff)-1);
                        buff[nread]=='\0';
                        /*客户数据请求完毕,关闭套接字,从集合中清除相应描述符 */
                        if (nread == 0)
                         {
    
    
                            close(fd);
                            memset(&fds[i], 0, sizeof(struct pollfd)); //去掉关闭的fd
                            printf("removing client on fd %d\n", fd);
                        }
                        /*处理客户数据请求*/
                        else
                        {
    
    
                            //read(fds[fd].fd, &ch, 1);
                            printf("serving client on fd %d, read: %s", fd, buff);
                            fds[i].events=POLLOUT;
                            /*ch++;*/
                            for(i=0; i<nread; i++){
    
    
                                /*if(buf[i]>='a' && buf[i]<='z'){
                                    buf[i] = buf[i] - 32;
                                }*/
                                buff[i] = toupper(buff[i]);
                            }
                           
                        }
                    } else if(fds[i].events&POLLOUT){
    
    
                            write(fd, buff, strlen(buff));
                            fds[i].events = POLLIN;
                    }
                  
                    
                }
            }
        }
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43507406/article/details/115188169