美文网首页
epoll高并发一般处理代码

epoll高并发一般处理代码

作者: hijiang | 来源:发表于2019-05-11 17:45 被阅读0次
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/epoll.h>
#include <fcntl.h>

#include <condition_variable>
#include <iostream>

bool g_exit = false;
void sigint_handler(int signo)
{
    g_exit = true;
}

int main(char argc, char *argv[])
{
    struct sigaction act, oldact;
    act.sa_handler = sigint_handler;
    sigemptyset(&act.sa_mask);
    sigaddset(&act.sa_mask, SIGINT);
    sigaction(SIGINT, &act, &oldact);

    int listen_sock = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
    int reuseaddr = 1;
    setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr));
    
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(1234);
    server_addr.sin_addr.s_addr = INADDR_ANY;
    
    if (bind(listen_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) != 0)
    {
        std::cout << "bind sock error" << std::endl;
        if (errno == EADDRINUSE)
        {
            std::cout << "addr already in use" << std::endl;
        }
        return -1;
    }

    int flag = fcntl(listen_sock, F_GETFL);
    flag |= O_NONBLOCK;
    fcntl(listen_sock, F_SETFL, flag);

    int ret = listen(listen_sock, 0);
    if (0 != ret)
    {
        if (errno == EADDRINUSE)
        {
            std::cout << "listen to socket error" << std::endl;
        }
        return -2;
    }

    int epoll_fd = epoll_create(1);
    struct epoll_event ev, evts[1024];
    ev.events = EPOLLIN | EPOLLET | EPOLLRDHUP;
    ev.data.fd = listen_sock;
    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_sock, &ev);

    while (1)
    {
        int nfd = epoll_wait(epoll_fd, evts, 1024, 100);
        if (nfd == -1)
        {
            if (errno == EINTR)
            {
                if (g_exit)
                {
                    break;
                }
                continue;
            }
            else
            {
                std::cout << "epoll error, errno=" << errno << std::endl;
                break;
            }
        }
        else if (nfd > 0)
        {
            for (int i = 0; i < nfd; i++)
            {
                if ((evts[i].events & EPOLLERR) || (evts[i].events & EPOLLRDHUP) || (evts[i].events & EPOLLHUP))
                {
                    if (evts[i].data.fd == listen_sock)
                    {
                        std::cout << "listen sock epoll error" << std::endl;
                        break;
                    }
                    else
                    {
                        if (0 != epoll_ctl(epoll_fd, EPOLL_CTL_DEL, evts[i].data.fd, NULL))
                        {
                            std::cout << "remove sock from epoll failed." << std::endl;
                        } 
                        else 
                        {
                            std::cout << "remove sock from epoll succeed." << std::endl;
                        }
                    }
                }

                if (evts[i].events & EPOLLIN)
                {
                    if (evts[i].data.fd == listen_sock)
                    { //进行连接操作
                        std::cout << "new acceptable sock" << std::endl;
                        // int accept_sock = accept4(listen_sock, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC);
                        int accept_sock = accept(listen_sock, NULL, NULL);

                        if (-1 == accept_sock)
                        {
                            if (EINTR == errno)
                            { //因为系统中断导致的错误,ET模式最好重新加入队列
                                struct epoll_event ev;
                                ev.events = EPOLLIN | EPOLLRDHUP | EPOLLET;
                                ev.data.fd = listen_sock;
                                epoll_ctl(epoll_fd, EPOLL_CTL_MOD, listen_sock, &evts[i]);
                            }
                            else
                            {
                                std::cout << "accept failed." << std::endl;
                            }
                        }
                        else if (accept_sock > 0)
                        {
                            int flag = fcntl(accept_sock, F_GETFL);
                            flag |= O_NONBLOCK;
                            fcntl(accept_sock, F_SETFL, flag);

                            struct epoll_event ev;
                            ev.events = EPOLLIN | EPOLLRDHUP | EPOLLET;
                            ev.data.fd = accept_sock;
                            if (0 != epoll_ctl(epoll_fd, EPOLL_CTL_ADD, accept_sock, &ev))
                            {
                                std::cout << "accpet sock add to epoll failed" << std::endl;
                            }
                            else
                            {
                                std::cout << "accept sock succeed, fd=" << accept_sock << std::endl;
                            }
                        }
                    } else {
                        //读取socket,调用fd绑定的处理对象处理
                    }
                }
                else if (evts[i].events & EPOLLOUT)
                {
                    //回调事件对象的写函数,事件对象自己将写的数据写出去
                }
            }
        }
        else
        {
            if (g_exit)
            {
                break;
            }
        }
    }
    close(epoll_fd);
    std::cout << "program exit succeed." << std::endl;
    return 0;
}

相关文章

  • epoll高并发一般处理代码

  • Nginx初探

    初识Nginx Nginx 特点 高并发,高性能epoll io 模型处理大并发请求32核64G服务器能支持100...

  • ❖ epoll方式 (从HTTP Server角度看)

    epoll是Linux内核采用的处理多任务高并发的一种方式。不同于多线程、多进程、协程、非阻塞等方式,epoll只...

  • 7.2、控制连入数,黑客攻击防范以及畸形包应对

    1、控制并发连入数量epoll技术支持数万高并发,但是在实际的业务中,单纯探讨epoll支持多少并发连接意义不是很...

  • 初识Nginx

    使用场景 特性 IO多路复用 使用epoll模型,高并发处理客户端的请求 CPU亲和 把working进程与CPU...

  • Nginx实现高并发及原理

    关键词:nginx 1、nginx基本介绍 1.nginx高并发原理(多进程(单线程)+epoll实现高并发) 1...

  • Nginx

    Nginx优点 支持海量高并发:采用IO多路复用epoll。官方测试Nginx能够支持5万并发链接,实际生产环境中...

  • 大数据入门学习

    常用处理方案 对于大量数据的处理方案:大量数据处理。 对于高并发的处理方案:高并发处理。 ============...

  • Nginx模块之echo

    选择nginx Nginx性能为王: 支持epoll,大规模高并发 支持Linux的sendfile系统调用,可以...

  • [libco] libco 不干活也费 CPU

    在 Linux 系统,libco 调用 epoll_wait 有点用力过猛,虽然 libco 针对高并发,但是小问...

网友评论

      本文标题:epoll高并发一般处理代码

      本文链接:https://www.haomeiwen.com/subject/xfqfaqtx.html