Unix系统编程(7) - I/O多路复用之poll

poll的机制与select类似,与select在本质上没有多大差别,管理多个描述符也是进行轮询,根据描述符的状态进行处理,但是poll没有最大文件描述符数量的限制
poll和select同样存在一个缺点就是,包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间,而不论这些文件描述符是否就绪,它的开销随着文件描述符数量的增加而线性增大。

服务端代码下载

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/time.h>
#include <poll.h>
#include <limits.h>

#define SERV_PORT 8000
#define MAXLINE 1024
#define OPEN_MAX 1024


int main()
{
    int listenfd, connfd;
    struct sockaddr_in server_addr, client_addr;    
    struct pollfd client[OPEN_MAX];
    int i = 0, maxi, nready, clientlen, sockfd, n;
    char buf[MAXLINE];

    listenfd = socket(AF_INET, SOCK_STREAM, 0);

    bzero(&server_addr, sizeof(server_addr));    
    server_addr.sin_port = htons(SERV_PORT);
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    bind(listenfd, (struct sockaddr *)&server_addr, sizeof(server_addr));

    listen(listenfd, 20);

    client[0].fd = listenfd;
    client[0].events = POLLRDNORM;
    for(i = 1; i < OPEN_MAX; ++i)
        client[i].fd  = -1;
    maxi = 0;

    for(;;)
    {
        nready = poll(client, maxi + 1, -1);
        if(client[0].revents & POLLRDNORM)              //新的客户端链接请求
        {
            clientlen = sizeof(client_addr);
            connfd = accept(listenfd, (struct sockaddr*)&client_addr, &clientlen);
            for(i=1; i<OPEN_MAX; ++i)
            {
                if(client[i].fd < 0)
                {
                    client[i].fd = connfd;
                    break;
                }
            }
            if(i == OPEN_MAX)
                printf("too many clients! \n ");
            client[i].events = POLLRDNORM;
            if(i > maxi)
                maxi = i;
            if(--nready <= 0)
                continue;
        }

        for(i=0; i<=maxi; ++i)
        {
            if((sockfd = client[i].fd) < 0)
                continue;
            if(client[i].revents & (POLLRDNORM | POLLERR))
            {
                if((n=read(client[i].fd, buf, sizeof(buf))) <= 0)
                {
                    close(client[i].fd);
                    client[i].fd = -1;
                }
                else
                    write(client[i].fd, buf, n);

                if(--nready <= 0)
                    break;
            }
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

空空的司马

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值