linux高性能服务器编程---第九章 I/O复用 (2)

poll

poll  

#include <poll.h>
// fds 结构体类型数组 指定我们感兴趣的文件描述符上发生的可读可写和异常事件\
// nfds 遍历结合大小 左闭右开
// timeout 单位为毫秒 -1 为阻塞 0 为立即返回
int poll(struct pollfd* fds, nfds_t nfds, int timeout);

struct pollfd
{
    int fd;
    short events;  //注册的事件, 告知poll监听fd上的哪些事件
    short revents; // 实际发生的事件
}
#define exit_if(r, ...) \
{   \
    if (r)  \
    {   \
        printf(__VA_ARGS__);    \
        printf("errno no: %d, error msg is %s", errno, strerror(errno));    \
        exit(1);    \
    }   \
}   \

struct client_info
{
    char *ip_;
    int port_;
};

int main(int argc, char* argv[])
{
    int port = 8001;
    char ip[] = "127.0.0.1";

    struct sockaddr_in address;
    address.sin_port = htons(port);
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = htons(INADDR_ANY);

    int listenfd = socket(PF_INET, SOCK_STREAM, 0);
    exit_if(listenfd < 0, "socket error\n");

    int ret = bind(listenfd, (struct sockaddr*)&address, sizeof(address));
    exit_if(ret == -1, "bind error\n");

    ret = listen(listenfd, 5);
    exit_if(ret == -1, "listen error\n");

    constexpr int MAX_CLIENTS = 1024;
    struct pollfd polls[MAX_CLIENTS] = {};
    struct client_info clientsinfo[MAX_CLIENTS] = {};

    polls[3].fd = listenfd;
    polls[3].events = POLLIN | POLLRDHUP;


    while (true)
    {
        ret = poll(polls, MAX_CLIENTS + 1, -1);
        exit_if(ret == -1, "poll error\n");

        for (int i = 3; i <= MAX_CLIENTS; ++i)
        {
            int fd = polls[i].fd;

            if (polls[i].revents & POLLRDHUP)
            {
                polls[i].events = 0;
                printf("close fd-%d from %s:%d\n", fd, clientsinfo[fd].ip_, clientsinfo[fd].port_);
            }

            if (polls[i].revents & POLLIN)
            {
                if (fd == listenfd)
                {
                    struct sockaddr_in client_address;
                    socklen_t client_addresslen = sizeof(client_address);

                    int clientfd = accept(listenfd, (struct sockaddr*)&client_address,
                            &client_addresslen);

                    struct client_info *clientinfo = &clientsinfo[clientfd];

                    clientinfo->ip_ = inet_ntoa(client_address.sin_addr);
                    clientinfo->port_ = ntohs(client_address.sin_port);

                    exit_if(clientfd < 0, "accpet error, from %s:%d\n", clientinfo->ip_,
                            clientinfo->port_);
                    printf("accept from %s:%d\n", clientinfo->ip_, clientinfo->port_);

                    polls[clientfd].fd = clientfd;
                    polls[clientfd].events = POLLIN | POLLRDHUP;
                }
                else
                {
                    char buffer[1024];
                    memset(buffer, '\0', sizeof(buffer));

                    ret = read(fd, buffer, 1024);
                    if(ret == 0)
                    {
                        close(fd);
                    }
                    else
                    {
                        printf("recv from %s:%d:\n%s\n", clientsinfo[fd].ip_,
                               clientsinfo[fd].port_, buffer);
                    }
                }
            }
        }
    }
}

 

posted @ 2022-06-01 16:05  马梦佳  阅读(36)  评论(0编辑  收藏  举报