栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

poll和epoll服务器(linux c)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/702465.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号