poll和epoll服务器(linux c)

poll和epoll服务器(linux c),第1张

poll和epoll服务器(linux c) poll

参考文章:https://blog.csdn.net/lianghe_work/article/details/46534029

头文件 #include

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

select用三个结构来记录信息,而poll只用一个结构

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 

#include 

#define MAXLNE 4096

#define POLL_SIZE 1024

int main(int argc, char **argv)
{
    int listenfd, connfd, n;
    struct sockaddr_in servaddr;
    char buff[MAXLNE];

    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        printf("create socket error: %s(errno: %d)n", strerror(errno), errno);
        return 0;
    }

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

    //指派迎宾员去哪个门口
    if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)
    {
        printf("bind socket error: %s(errno: %d)n", strerror(errno), errno);
        return 0;
    }

    //开始迎宾
    if (listen(listenfd, 10) == -1)
    {
        printf("listen socket error: %s(errno: %d)n", strerror(errno), errno);
        return 0;
    }

    struct pollfd fds[POLL_SIZE] = {0};
    fds[listenfd].fd = listenfd;
    fds[listenfd].events = POLLIN;

    int max_fd = listenfd;

    while (1)
    {
        int nready = poll(fds, max_fd + 1, -1);
        if (fds[listenfd].revents & POLLIN)
        {
            struct sockaddr_in client;
            socklen_t len = sizeof(client);
            if ((connfd = accept(listenfd, (struct sockaddr *)&client, &len)) == -1)
            {
                printf("accept socket error: %s(errno: %d)n", strerror(errno), errno);
                return 0;
            }

            fds[connfd].fd = connfd;
            fds[connfd].events = POLLIN;

            if (connfd > max_fd)
                max_fd = connfd;

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

        int i = 0;
        for (i = listenfd + 1; i <= max_fd; i++)
        {
            if (fds[i].revents & POLLIN)
            {
                n = recv(i, buff, MAXLNE, 0);
                if (n > 0)
                {
                    buff[n] = '';
                    printf("recv msg from client: %sn", buff);

                    send(i, buff, n, 0);
                }
                else if (n == 0)
                {
                    fds[i].fd = -1;
                    close(i);
                }

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

    close(listenfd);
    return 0;
}
epoll

参考博客:https://cloud.tencent.com/developer/article/1698629

2.6的版本以前,linux只能用来做嵌入式,随着epoll的出现,linux才被用作服务器,一些框架的底层离不开epoll,服务器核心的点,就是24小时无间断的死循环while(1),

select 和 poll都是我们主动去搜寻事件,而epoll是由它来告诉我们那里来了事件

头文件:#include

epoll_create : 只有一个参数,填大于0就可以 ,之前是用数组存储,现在是用链表,但是为了兼容之前的代码,所以把这个形参留下来了。

epoll_ctl --> add、delete、modify

创建一栋楼:epoll_create

添加一个住户:epoll_ctl -->  add

删除一个住户:epoll_ctl --> delete

修改一个住户:epoll_ctl -->modify

快递员装快递的盒子: struct epoll_event events[POLL_SIZE] = {0}; 

楼下有一个蜂巢

快递员多久来取一次快递:epoll_wait 
快递员取完快递后交给应用层

recv完直接send的写法:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 

#include 

#define MAXLNE 4096

#define POLL_SIZE 1024

int main(int argc, char **argv)
{
    int listenfd, connfd, n;
    struct sockaddr_in servaddr;
    char buff[MAXLNE];

    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        printf("create socket error: %s(errno: %d)n", strerror(errno), errno);
        return 0;
    }

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

    //指派迎宾员去哪个门口
    if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)
    {
        printf("bind socket error: %s(errno: %d)n", strerror(errno), errno);
        return 0;
    }

    //开始迎宾
    if (listen(listenfd, 10) == -1)
    {
        printf("listen socket error: %s(errno: %d)n", strerror(errno), errno);
        return 0;
    }

    int epfd = epoll_create(1);

    struct epoll_event events[POLL_SIZE] = {0}; //快递员盒子的大小
    struct epoll_event ev;

    ev.events = EPOLLIN;
    ev.data.fd = listenfd;

    epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev);

    while (1)
    {
        //快递员取快递,-1表示有了快递才去取
        int nready = epoll_wait(epfd, events, POLL_SIZE, -1);
        if (nready == -1)
        {
            continue;
        }

        int i = 0;
        for (i = 0; i < nready; i++)
        {
            int clientfd = events[i].data.fd;
            if (clientfd == listenfd)
            {
                //对listenfd进行处理
                struct sockaddr_in client;
                socklen_t len = sizeof(client);
                if ((connfd = accept(listenfd, (struct sockaddr *)&client, &len)) == -1)
                {
                    printf("accept socket error: %s(errno: %d)n", strerror(errno), errno);
                    return 0;
                }

                ev.events = EPOLLIN;
                ev.data.fd = connfd;
                epoll_ctl(epfd, EPOLL_CTL_ADD, connfd, &ev);
            }
            else if (events[i].events & EPOLLIN)
            {
                //对所有的connfd进行处理
                n = recv(clientfd, buff, MAXLNE, 0);
                if (n > 0)
                {
                    buff[n] = '';
                    printf("recv msg from client: %sn", buff);

                    send(clientfd, buff, n, 0);
                }
                else if (n == 0)
                {
                    ev.events = EPOLLIN;
                    ev.data.fd = clientfd;
                    epoll_ctl(epfd, EPOLL_CTL_DEL, clientfd, &ev);
                    close(clientfd);
                }
            }
        }
    }

    close(listenfd);
    return 0;
}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5702571.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存