Esempio n. 1
0
void
myEpoll::start()
{
//	sock.Socket(AF_INET, SOCK_STREAM, 0);

    listen_sock = sock.getListen();

    sock.Bind(listen_sock);

    sock.Listen(listen_sock);
    // FIXME Я не считаю таки обертки (своя ОО обертка вокруг каждой C-функции) правильными...
    // Сделать из пары C++ и glibc подобие Python - не является смоцелью, а просто тратой времени
    // и усложнение кода.
    // Проще в одном методе (типа этого) позвать сразу все Сишные функции с проверками результата
    // и выбросом исклчений - так Си код изолируется от C++ кода без потери 'красоты', но
    // экономией времени.
    // Если нужны OO сокеты, то есть Boost::asio... Хуже того, ОО сокеты вообще никому не нужны
    // на самом деле, а нужны уже готовые паттерны типа реактора и проактора ( с уже реализованным
    // epoll и пр.)

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

    epollfd = Epoll_create(MAX_EVENTS);

    Epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_sock, &ev);

}
Esempio n. 2
0
void
myEpoll::loop()
{
    if(!handler) {
        perror("loop: do_use_fd no defined");
    }
    for (;;) {
        nfds = Epoll_wait(epollfd, events, MAX_EVENTS, -1);
        int n;
        for (n = 0; n < nfds; ++n) {
            if (events[n].data.fd == listen_sock) {

                conn_sock = sock.Accept(listen_sock);

                std::cout << "new client: " << sock.Sock_ntop() << std::endl;

                sock.setnonblocking(conn_sock);
                write(conn_sock, hello, strlen(hello) ); //!!aghtung send helloworld!!

                //		do_use_fd(conn_sock); //! ololo del

                ev.events = EPOLLIN | EPOLLET;
                ev.data.fd = conn_sock;

                if( Epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock, &ev) < 0) {
                    perror("loop: Epoll_ctl");
                }

            } else {
                // by analogy with True branch, epoll ok
                printf("READY\n");
                //! do use fd
                (*handler) (events[n].data.fd);
                // FIXME да, звать прикладную логику через хендлер - очень хорошее решение.
                // Примерно то, что делает Boost::asio и, может быть, libevent
                // Хотя... Не всегда это нужно...
                // Суть в том, что для маленьких проектов важна скорость разработки без
                // потери качества (легкости, надежности и производительности) кода.
                // Такие же generic-решения хороши для намного больших проектов.
                // Предугадываться же какие части будут использоватсья в другом проекти
                // или расширяться в существующем - это не всегда тревиальный вопрос.
            }
        }
    }
}
Esempio n. 3
0
void Server::StringServerByEpollET()
{
    int connfd, epollfd, maxindex;
    struct epoll_event ev;
    struct epoll_event events[MAX_EVENTS];

    maxindex = -1;
    const int listenfd = m_ListenFd;

    epollfd = Epoll_create(MAX_EVENTS);

    memset(&ev, 0, sizeof(struct epoll_event));
    memset(events, 0, sizeof(struct epoll_event) * MAX_EVENTS);

    ev.events = EPOLLIN | EPOLLET;
    ev.data.fd = listenfd;
    SetNonBlocking(listenfd);
    Epoll_ctl(epollfd, EPOLL_CTL_ADD, listenfd, &ev);

    for (;;)
    {
        int i, j, nready;

        /*
        * Need to use the original epoll_wait(), rather
        * than the wrapped Epoll_wait(), the same reason
        * as select() above
        */

        nready = epoll_wait(epollfd, events, MAX_EVENTS, -1);

        if ((nready == -1) && (errno == EINTR) && (m_ExitFlag == 1))
            break;

        else if ((nready == -1) && (errno == EINTR) && (m_ExitFlag == 0))
            continue;

        else if (nready == -1)
        {
            std::cout << "epoll_wait error: ";
            std::cout << strerror(errno) << std::endl;
            exit(-1);
        }

        for (i = 0; i < nready; i++)
        {
            /* new connection request */
            if (events[i].data.fd == listenfd && events[i].events & EPOLLIN)
            {
                sockaddr_in cliaddr;
                socklen_t clilen = sizeof(cliaddr);

                // need to use the original 'accept' to handle EWOULDBLOCK
                if ((connfd = accept(listenfd, (struct sockaddr*)&cliaddr, &clilen)) < 0)
                {
                    if (connfd == EWOULDBLOCK)
                        continue;

                    else
                    {
                        std::cout << "accept error: ";
                        std::cout << strerror(errno) << std::endl;

                        return;
                    }
                }

                std::cout << "a connection has been established on fd: " << connfd << std::endl;

                if (m_ClientCount >= MAX_EVENTS)
                {
                    std::cout << "too many clients" << std::endl;
                    Close(connfd);
                    continue;
                }

                for (j = 0; j < MAX_EVENTS; j++)
                {
                    if (m_ClientFds[j] == -1)
                    {
                        m_ClientFds[j] = connfd;
                        m_ClientsBuffers[j] = new char[BUFFER_SIZE];
                        m_ClientCount++;
                        break;
                    }
                }

                if (j > maxindex)
                    maxindex = j;

                ev.events = EPOLLIN | EPOLLOUT | EPOLLET;
                ev.data.fd = connfd;
                SetNonBlocking(connfd);
                Epoll_ctl(epollfd, EPOLL_CTL_ADD, connfd, &ev);
            }

            else
            {
                char* buf;
                int sockfd;
                ssize_t nread, nwrite;

                // pointers for buffer control
                char *pbufi, *pbufo;

                /* check all clients for data */
                for (j = 0; j <= maxindex; j++)
                {
                    if (m_ClientFds[j] == -1)
                        continue;

                    sockfd = m_ClientFds[j];

                    if (sockfd == events[i].data.fd)
                    {
                        buf = m_ClientsBuffers[j];
                        pbufi = pbufo = buf;
                        break;
                    }
                }

                // read event on client[j]
                if (events[i].events & EPOLLIN)
                {
                    // need to use the original 'read' to handle EWOULDBLOCK
                    if ((nread = read(sockfd, pbufi, (buf + BUFFER_SIZE - pbufi))) < 0)
                    {
                        if (errno != EWOULDBLOCK)
                        {
                            std::cout << "read socket error: ";
                            std::cout << strerror(errno) << std::endl;

                            // terminate
                            return;
                        }
                    }

                    // handle 'EOF' on sockfd
                    else if (nread == 0)
                    {
                        Epoll_ctl(epollfd, EPOLL_CTL_DEL, sockfd, &ev);
                        std::cout << "client has closed connection" << std::endl;
                        Close(m_ClientFds[j]);
                        m_ClientFds[j] = -1;
                        delete [] m_ClientsBuffers[j];
                        m_ClientsBuffers[j] = NULL;
                        m_ClientCount--;
                    }

                    // normal state
                    else
                        pbufi += nread;
                }

                // write event on client[j]
                if (events[i].events & EPOLLOUT && (pbufi - pbufo > 0))
                {
                    int bytestowrite = pbufi - pbufo;

                    // need to use the original 'write' to handle EWOULDBLOCK
                    if ((nwrite = write(sockfd, pbufo, bytestowrite)) < 0)
                    {
                        if (errno != EWOULDBLOCK)
                        {
                            std::cout << "write socket error: ";
                            std::cout << strerror(errno) << std::endl;

                            // terminate
                            return;
                        }
                    }

                    else
                    {
                        pbufo += nwrite;

                        if(pbufo == pbufi)
                            pbufi = pbufo = buf;
                    }
                }
            }
        }
    }

    // exiting
    Close(epollfd);
}
Esempio n. 4
0
void Server::StringServerByEpollLT()
{
    int connfd, epollfd, maxindex;
    struct epoll_event ev;
    struct epoll_event events[MAX_EVENTS];

    maxindex = -1;
    const int listenfd = m_ListenFd;

    epollfd = Epoll_create(MAX_EVENTS);

    memset(&ev, 0, sizeof(struct epoll_event));
    memset(events, 0, sizeof(struct epoll_event) * MAX_EVENTS);

    ev.events = EPOLLIN;
    ev.data.fd = listenfd;
    Epoll_ctl(epollfd, EPOLL_CTL_ADD, listenfd, &ev);

    for (;;)
    {
        int i, j, nready;

        /*
        * Need to use the original epoll_wait(), rather
        * than the wrapped Epoll_wait(), the same reason
        * as select() above
        */

        nready = epoll_wait(epollfd, events, MAX_EVENTS, -1);

        if ((nready == -1) && (errno == EINTR) && (m_ExitFlag == 1))
            break;

        else if ((nready == -1) && (errno == EINTR) && (m_ExitFlag == 0))
            continue;

        else if (nready == -1)
        {
            std::cout << "epoll_wait error: ";
            std::cout << strerror(errno) << std::endl;
            exit(-1);
        }

        for (i = 0; i < nready; i++)
        {
            /* new connection request */
            if (events[i].data.fd == listenfd)
            {
                sockaddr_in cliaddr;
                socklen_t clilen = sizeof(cliaddr);

                connfd = Accept(listenfd, (struct sockaddr*)&cliaddr, &clilen);

                std::cout << "a connection has been established on fd: " << connfd << std::endl;

                if (m_ClientCount >= MAX_EVENTS)
                {
                    std::cout << "too many clients" << std::endl;
                    Close(connfd);
                    continue;
                }

                for (j = 0; j < MAX_EVENTS; j++)
                {
                    if (m_ClientFds[j] == -1)
                    {
                        m_ClientFds[j] = connfd;
                        m_ClientsBuffers[j] = new char[BUFFER_SIZE];
                        m_ClientCount++;
                        break;
                    }
                }

                if (j > maxindex)
                    maxindex = j;

                ev.events = EPOLLIN | EPOLLET;
                ev.data.fd = connfd;
                Epoll_ctl(epollfd, EPOLL_CTL_ADD, connfd, &ev);
            }

            else
            {
                char* buf;
                int sockfd;
                ssize_t nread;

                /* check all clients for data */
                for (j = 0; j <= maxindex; j++)
                {
                    if (m_ClientFds[j] == -1)
                        continue;

                    sockfd = m_ClientFds[j];

                    if (sockfd == events[i].data.fd)
                    {
                        buf = m_ClientsBuffers[j];
                        break;
                    }
                }

                if ((nread = Read(sockfd, buf, BUFFER_SIZE)) == 0)
                {
                    Epoll_ctl(epollfd, EPOLL_CTL_DEL, sockfd, &ev);
                    std::cout << "client has closed connection" << std::endl;
                    Close(m_ClientFds[j]);
                    m_ClientFds[j] = -1;
                    delete [] m_ClientsBuffers[j];
                    m_ClientsBuffers[j] = NULL;
                    m_ClientCount--;
                }

                else if(nread > 0)
                    Write(sockfd, buf, nread);
            }
        }
    }

    // exiting
    Close(epollfd);
}
Esempio n. 5
0
myEpoll::~myEpoll()
{
//	Epoll_ctl(epollfd, EPOLL_CTL_DEL, 0, NULL);
    Epoll_ctl(epollfd, EPOLL_CTL_DEL, listen_sock, &ev);
    close(epollfd);
}