poll 示例
博客专区 > for。 的博客 > 博客详情
poll 示例
for。 发表于2年前
poll 示例
  • 发表于 2年前
  • 阅读 39
  • 收藏 1
  • 点赞 0
  • 评论 0

标题:腾讯云 新注册用户域名抢购1元起>>>   

摘要: poll 示例

poll 使用的结构体如下

struct pollfd {
    int   fd;         /* file descriptor */
    short events;     /* requested events */
    short revents;    /* returned events */
};

需要使用该结构体数组对文件描述符进行注册,poll 通过该数组返回结果。事件就绪时需要遍历所有注册的文件描述符。

源码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <poll.h>
#include <sys/stropts.h>

#define SERV_PORT   9000
#define LISTENQ     10
#define OPEN_MAX    1024
#define MAXLINE     1024

int main(int argc, char **argv)
{
    int         listenfd, connfd, sockfd;
    int         nready, maxi, i, n;
    socklen_t   clilen;
    struct sockaddr_in  cliaddr, servaddr;
    struct pollfd       client[OPEN_MAX];
    char        buf[MAXLINE];

    /* 创建 socket */
    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);

    /* 绑定地址到 socket */
    if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
        perror("bind");
        exit(EXIT_FAILURE);
    }

    /* 转为监听 socket */
    if (listen(listenfd, LISTENQ)) {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    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, 1000);
        if (nready < 0) {
            perror("poll");
            exit(EXIT_FAILURE);
        } else if (nready == 0) {
            fprintf(stderr, "timeout\n");
        }

        if (client[0].revents & POLLRDNORM) {
            /* 监听 socket 上读事件 */
            clilen = sizeof(cliaddr);
            connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
            if (connfd == -1) {
                perror("accept");
                continue;
            }
            fprintf(stderr, "accept %d\n", connfd);

            /* 从client 数组中找到一个空位 */
            for (i = 1; i < OPEN_MAX; i++) {
                if (client[i].fd < 0) {
                    client[i].fd = connfd;
                    break;
                }
            }

            if (i == OPEN_MAX) {
                fprintf(stderr, "too many clients");
                exit(EXIT_FAILURE);
            }

            client[i].events = POLLRDNORM;
            if (i > maxi) {
                maxi = i;
            }

            if (--nready <= 0) {
                continue;
            }
        }

        /* 剩余的文件描述符 */
        for (i = 1; i <= maxi; ++i) {
            if ((sockfd = client[i].fd) < 0)
                continue;
            if (client[i].revents & (POLLRDNORM | POLLERR)) {
                /* 读事件 */
                if ((n = read(sockfd, buf, MAXLINE)) < 0) {
                    if (errno == ECONNRESET) {
                        close(sockfd);
                        client[i].fd = -1;
                    } else {
                        fprintf(stderr, "read error");
                    }
                } else if (n == 0) {
                    /* 客户端关闭连接 */
                    close(sockfd);
                    client[i].fd = -1;
                } else {
                    /* 回写数据到客户端 */
                    write(sockfd, buf, n);
                }

                if (--nready <= 0) {
                    break;
                }
            }
        }
    }

    return 0;
}

参考资料

《UNP》

标签: linux poll 网络编程
共有 人打赏支持
for。
粉丝 76
博文 47
码字总数 18257
×
for。
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: