美文网首页
epoll 封装

epoll 封装

作者: imsjw | 来源:发表于2019-01-29 10:25 被阅读0次

    dwsocket.h

    #pragma once
    
    #include <string>
    #include <sys/epoll.h>
    
    namespace dw {
    
        using namespace std;
    
        class Addr
        {
        public:
            int port;
            string ip;
            Addr(string ip, int port);
            Addr();
            ~Addr();
            friend ostream& operator<<(ostream &out, const Addr &addr);
        private:
    
        };
    
    
        /*
         * 服务端Socket 完全异步
         */
        class ServerSocket
        {
        public:
            Addr *addr = NULL;
            int maxListenNum = 128;//最大监听数,libevent也是128
            int epollSize = 65535;//epoll 的最大监听数
            int maxEvents = 1024;
            int maxThread = 1; //最大线程数(socket开启时,会会根据cpu核心数,重新初始化该值)
    
            ServerSocket(int port);
            ~ServerSocket();
            int start();
    
        private:
            int socketfd = -1;
            int epollfd = -1;
            epoll_event* events;
    
            void initAddr(int port);
            int initSocket();
            int initEpoll();
            void setNonBlock(int fd); //设置非阻塞socket
            void initMaxThread();
            void loopWait();
            void addSocketFd(int fd);
            int initThreadPool(); //初始化线程池
        };
    
    }
    

    Addr.cpp

    #include "dwsocket.h"
    
    #include<iostream>
    
    namespace dw {
    
        Addr::Addr() {
        }
    
        Addr::Addr(string ip, int port) {
            this->port = port;
            this->ip = ip;
        }
    
        Addr::~Addr() {
        }
    
        ostream& operator<<(ostream &out, const Addr &addr) {
            out << addr.ip << ":" << addr.port;
            return out;
        }
    
    
    }
    

    ServerSocket.cpp

    #include "dwsocket.h"
    
    #include<iostream>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <fcntl.h>
    #include <sys/sysinfo.h>
    
    namespace dw {
    
        using namespace std;
    
        ServerSocket::ServerSocket(int port) {
            initAddr(port);
            initMaxThread();
        }
    
        ServerSocket::~ServerSocket() {
            delete addr;
            shutdown(socketfd, SHUT_RDWR);
        }
    
        void ServerSocket::initMaxThread() {
            int cpuCoreNum = get_nprocs();
            maxThread = cpuCoreNum * 2;
        }
    
    
        void ServerSocket::initAddr(int port) {
            addr = new Addr("127.0.0.1", port);
        }
    
        int ServerSocket::initSocket() {
            if (maxListenNum <= 0) {
                cout << "Error: maxListenNum 必须大于0 " << endl;
                return -1;
            }
    
            socketfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
            if (socketfd < 0) {
                cout << "Error: socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)" << endl;
                return -1;
            }
    
            //设置socket
            setNonBlock(socketfd);
            int opt = 1;
            setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    
            struct sockaddr_in server_addr;
            server_addr.sin_family = AF_INET;
            server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
            server_addr.sin_port = htons(addr->port);
    
            int err = bind(socketfd, (struct sockaddr*) &server_addr, sizeof(server_addr));
            if (err < 0) {
                cout << "Error: bind(socketfd, (struct sockaddr*) &server_addr, sizeof(server_addr))" << endl;
                return -1;
            }
    
            err = listen(socketfd, maxListenNum);
            if (err < 0) {
                cout << "Error: listen(socketfd, maxListenNum)" << endl;
                return -1;
            }
    
            return 0;
        }
    
        void ServerSocket::setNonBlock(int fd) {
            int fl = fcntl(socketfd, F_GETFL);
            fcntl(socketfd, F_SETFL, fl | O_NONBLOCK);
        }
    
        int ServerSocket::initEpoll() {
    
            epollfd = epoll_create(epollSize);
            if (epollfd < 0) {
                cout << "Error: epoll_create(maxEvents)" << endl;
                return -1;
            }
    
            events = new epoll_event[maxEvents];
            addSocketFd(socketfd);
    
            return 0;
        }
    
        void ServerSocket::loopWait() {
    
            struct sockaddr_in clientaddr;
            socklen_t clilen = sizeof(clientaddr);
    
            while (1) {
                int num = epoll_wait(epollfd, events, maxEvents, -1); //返回活跃用户个数
                for (int i = 0; i < num; i++) {
                    int connfd = -1;
                    if (events[i].data.fd == socketfd) {
                        //新连接
                        cout << "新连接" << endl;
                        connfd = accept(socketfd, (struct sockaddr *) &clientaddr, &clilen);
                        if (connfd < 0) {
                            cout << "连接失败" << endl;
                            continue;
                        }
                        setNonBlock(connfd);
                    }
                    else if (events[i].events&EPOLLIN) {
                        //以前的连接,有数据读取
                        cout << "以前的连接 读取" << endl;
                        if ((connfd = events[i].data.fd) < 0) {
                            cout << "连接失败" << endl;
                            continue;
                        }
                    }
                    else if (events[i].events&EPOLLOUT) {
                        //以前的连接,有数据写出
                        cout << "以前的连接 写出" << endl;
                    }
                    else {
                        cout << "其他" << endl;
                        continue;
                    }
                    addSocketFd(connfd);
                }
            }
        }
    
        void ServerSocket::addSocketFd(int fd) {
            struct epoll_event event;
            event.data.fd = fd;
            event.events = EPOLLIN | EPOLLET;
            epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);
        }
    
        int ServerSocket::start() {
            int err = initSocket();
            if (err < 0) {
                cout << "Error: initSocket()" << endl;
                return -1;
            }
    
            err = initEpoll();
            if (err < 0) {
                cout << "Error: initEpoll()" << endl;
                return -1;
            }
            loopWait();
            return 0;
        }
    }
    

    相关文章

      网友评论

          本文标题:epoll 封装

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