I/O多路转接(二)——poll函数

I/O多路转接(二)——poll函数

第二篇介绍poll函数,不说废话直接来看函数。
int poll(struct pollfd *fds, nfds_t nfds, int timeout);

返回值
大于0,准备就绪的file descriptor数量;等于0,超时;小于0,出错。

参数
fds:
struct pollfd {
int fd; //file descriptor
short events; // 关心这个fd的什么事件 用宏设置我们只关心读POLLIN写POLLOUT
short revents; // 事件是否就绪
};
nfds:关心的fd数量
timeout:等待时间单位毫秒 -1,永久等待;0,不等待直接检测返回;>0,等待时间

poll的特点

  1. 与select不同,将输入与输出分开不需要每次调用前重新设置。
  2. 与select相同, 每次都要将fd_array集合由用户态向内核态拷贝,在内核态要遍历fd_array,fd数量增多性能下降损失很大。
  3. 解决了select有上限的问题,大小可至操作系统允许的最大,使cat/proc/sys/fs/file-max可以查看。

使用poll函数的网络服务器
server.c

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int startup(char*ip,int port)
{
    int sock = socket(AF_INET,SOCK_STREAM,0);
    if(sock < 0){
        perror("socket");
        return 2;
    }

    struct sockaddr_in local;
    local.sin_family = AF_INET;
    local.sin_port = htons(port);
    local.sin_addr.s_addr = inet_addr(ip);

    if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0){
        perror("bind");
        return 3;
    }

    if(listen(sock,10) < 0){
        perror("listen");
        return 4;
    }
    return sock;
}

int main(int argc,char *argv[])
{
    if(argc!= 3){
        printf("Usage:%s [ip] [port]\n",argv[0]);
        return 1;
    }
    int listen_sock = startup(argv[1],atoi(argv[2]));
    printf("listen_sock has been created,the value is %d\n",listen_sock);

    //监听套接字创建完成,等待读事件发生。
    struct pollfd fd_array[1024];
    int i = 0;
    int size = 1024;
    for(;i//初始化数组。
        fd_array[i].fd = -1;
    }
    //数组第一个位置永远保存监听套接字描述符。
    fd_array[0].fd = listen_sock;
    fd_array[0].events = POLLIN;
    while(1){
        int ret = poll(fd_array,size,1000);
        switch(ret){
            case 0:
                printf("timeout\n");
                break;
            case -1:
                perror("select");
                break;
            default:
                {
                    //一一查看所关心的读事件描述符是否发生状态改变
                    for(i= 0;i < size;i++){
                        if(fd_array[i].fd < 0)
                            continue;
                        if(i== 0&& fd_array[i].revents&POLLIN){//listen_sock描述符状态改变说明有client请求连接
                            struct sockaddr_in client;
                            socklen_t len = sizeof(client);
                            int new_sock = accept(listen_sock,(struct sockaddr*)&client,&len);
                            if(new_sock < 0){
                                perror("accept");
                                continue;
                            }else{
                                printf("get a client!ip:%s,port:%d\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
                                for(i= 0;i//找到一个未被占用的位置存放新链接的描述符。
                                    if(fd_array[i].fd< 0){
                                        fd_array[i].fd= new_sock;
                                        fd_array[i].events = POLLIN;
                                        break;
                                    }
                                }
                                if(i==size){
                                    close(new_sock);
                                    printf("server is full\n");
                                }
                            }
                        }else if(i!= 0&&fd_array[i].revents&POLLIN){//其他关心描述符状态改变。
                            char buf[1024];
                            ssize_t s = read(fd_array[i].fd,buf,sizeof(buf)-1);
                            if(s >0){
                                buf[s]= 0;
                                printf("client say# %s\n",buf);
                            }else if(s==0){
                                printf("client is quit!\n");
                                close(fd_array[i].fd);
                                fd_array[i].fd= -1;
                            }else{
                                perror("read");
                                close(fd_array[i].fd);
                                fd_array[i].fd= -1;
                            }
                        }
                    } 
                }
                break; 
        }
    }
    return 0;
}

你可能感兴趣的:(linux)