Sponsored Content
Top Forums Programming Event driven programming / epoll / typedef union / session data array Post 302918112 by John S. on Sunday 21st of September 2014 06:31:05 PM
Old 09-21-2014
Big picture of code - sorry for not posting before...

My apologies to Corona688 and others following this.

Please remember, over 90% of this is Lrrr's code as found here.
epoll_wait: Linux sockets example

I've commented out moving fd BACK to where it had recently been taken FROM and it seems to work great.

I've also found one spot to free the SessionData and plug the memory leak.


Code:
// 10,000 to solve C10K problem, yes? YES. see http://lse.sourceforge.net/epoll/
#define EPOLL_ARRAY_SIZE   64


void sprint_buffer(const char *buffer, int size)
{
   int i;
   for (i = 0; i < size; i++)
   {
      if (isprint(buffer[i]))
         printf("%c", buffer[i]);
      else
         printf("\\0x%02X", buffer[i]);
   }
}






struct SessionData
{
    int FileDescriptor;
    int Data1;
    int Data2;
    int Data3;
};

void Tests()
{

    //http://epollwait.blogspot.com/2010/11/linux-sockets-example.html
    //
    //int main(int argc, char *argv[])
    //{
    int sd, efd, clientsd, fd; // socket descriptor, epoll file descriptor, client socket descriptor, file descriptor
    struct sockaddr_in bindaddr, peeraddr;
    socklen_t salen = sizeof(peeraddr);
    int pollsize = 1;
    struct epoll_event ev;
    struct epoll_event epoll_events[EPOLL_ARRAY_SIZE];
    uint32_t events;
    //unsigned short port = 20000;
    unsigned short port = 3333;
    int i, rval, on = 1;
    ssize_t rc;
    char buffer[1024];

    struct SessionData * SessionData;

    efd = epoll_create(pollsize);

    if (efd < 0)
    {
       printf("Could not create the epoll fd: %m");
       //return 1;
       return;
    }

    sd = socket(AF_INET, SOCK_STREAM, 0);
    if (sd < 0)
    {
        printf("Could not create new socket: %m\n");
        //return 2;
        return ;
    }

    printf("New socket created with sd %d\n", sd);

    if (fcntl(sd, F_SETFL, O_NONBLOCK))
    {
       printf("Could not make the socket non-blocking: %m\n");
       close(sd);
       //return 3;
       return ;
    }

    if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
    {
       printf("Could not set socket %d option for reusability: %m\n", sd);
       close(sd);
       //return 4;
       return ;
    }

    bindaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    bindaddr.sin_family= AF_INET;
    bindaddr.sin_port = htons(port);

    if (bind(sd, (struct sockaddr *) &bindaddr, sizeof(struct sockaddr_in)) < 0)
    {
       printf("Could not bind socket %d to address 'INADDR_ANY' and port %u: %m", sd, port);
       close(sd);
       //return 5;
       return ;
    }
    else
    {
       printf("Bound socket %d to address 'INADDR_ANY' and port %u\n", sd, port);
    }

    if (listen(sd, SOMAXCONN))
    {
       printf("Could not start listening on server socket %d: %m\n", sd);
       goto cleanup;
    }
    else
    {
       printf("Server socket %d started listening to address 'INADDR_ANY' and port %u\n", sd, port);
    }

    ev.events = EPOLLIN;
    //ev.data.u64 = 0LL; // 0 Long Long
    //ev.data.fd = sd;

    SessionData = malloc(sizeof(SessionData));
    SessionData->FileDescriptor = sd;
    //SessionData->Data1 = 1;
    //SessionData->Data2 = 2;
    //SessionData->Data3 = 3;
    ev.data.ptr = SessionData;

    //ev.data.ptr = 0;






    if (epoll_ctl(efd, EPOLL_CTL_ADD, sd, &ev) < 0)
    {
        printf("Couldn't add server socket %d to epoll set: %m\n", sd);
        goto cleanup;
    }

    for (;;)
    {
        //ReWait:

        printf("Starting epoll_wait on %d fds\n", pollsize);

        //while ((rval = epoll_wait(efd, epoll_events, EPOLL_ARRAY_SIZE, -1)) < 0)
        while ((rval = epoll_wait(efd, epoll_events, EPOLL_ARRAY_SIZE, 10000)) < 0) // 10 second timeout
        {
            if ((rval < 0) && (errno != EINTR))
            {
                printf("EPoll on %d fds failed: %m\n", pollsize);
                goto cleanup;
            }
        }

        //if we include a timeout
        if (rval == 0)
        {
            // handle timeout and return to wait
            printf("EPoll timeout\n");
            //goto ReWait;
        }



        for (i = 0; i < rval; i++)
        {
            events = epoll_events[i].events;
            //fd = epoll_events[i].data.fd;
            fd = ((struct SessionData *) epoll_events[i].data.ptr)->FileDescriptor;

            if (events & EPOLLERR)
            {
                if (fd == sd)
                {
                    printf("EPoll on %d fds failed: %m\n", pollsize);
                    // could free SessionData here but why bother?
                    goto cleanup;
                } else
                {
                    printf("Closing socket with sd %d\n", fd);
                    shutdown(fd, SHUT_RDWR);
                    close(fd);
                    free(((struct SessionData *) epoll_events[i].data.ptr)); // is free needed anywhere else?
                    continue;
                }
            }

            if (events & EPOLLWAKEUP) // MY ADDITION
            {
                printf("EPoll timeout\n");
            }

            if (events & EPOLLHUP)
            {
                if (fd == sd)
                {
                    printf("EPoll on %d fds failed: %m\n", pollsize);
                    goto cleanup;
                } else
                {
                    printf("Closing socket with sd %d\n", fd);
                    shutdown(fd, SHUT_RDWR);
                    close(fd);
                    continue;
                }
            }

            if (events & EPOLLRDHUP)
            {
                if (fd == sd)
                {
                    printf("EPoll on %d fds failed: %m\n", pollsize);
                    goto cleanup;
                } else
                {
                    printf("Closing socket with sd %d\n", fd);
                    shutdown(fd, SHUT_RDWR);
                    close(fd);
                    continue;
                }
            }

            if (events & EPOLLOUT)
            {
                if (fd != sd)
                {
                    //rc = snprintf(buffer, sizeof(buffer), "Hello socket %d from server socket %d!\n", fd, sd);
                    //rc = snprintf(buffer, sizeof(buffer), "Hello socket %d from server socket %d!\n", fd, sd);
                    //rc = snprintf(buffer, sizeof(buffer), "Hello socket %d from server socket %d!\n", fd, sd);
                    //rc = snprintf(buffer, sizeof(buffer), "Hello socket %d from server socket %d!\n", fd, sd);
                    rc = snprintf(buffer, sizeof(buffer), "Hello socket %d from server socket %d! Session data: %d\n", fd, sd, ((struct SessionData *) epoll_events[i].data.ptr)->Data1 ++);
                    while ((rc = send(fd, buffer, rc, 0)) < 0)
                    {
                        if ((fd < 0) && (errno != EINTR))
                        {
                            printf("Send to socket %d failed: %m\n", fd);
                            pollsize--;
                            shutdown(fd, SHUT_RDWR);
                            close(fd);
                            continue;
                        }
                    }

                    if (rc == 0)
                    {
                        printf("Closing socket with sd %d\n", fd);
                        pollsize--;
                        shutdown(fd, SHUT_RDWR);
                        close(fd);
                        continue;
                    } else if (rc > 0)
                    {
                        printf("Sent '");
                        sprint_buffer(buffer, rc);
                        printf("' to socket with sd %d\n", fd);

                        ev.events = EPOLLIN;
                        //ev.data.u64 = 0LL;
                        //ev.data.fd = fd;
                        //(struct SessionData *) ev.data.ptr->FileDescriptor = fd;
         //               ((struct SessionData *) ev.data.ptr)->FileDescriptor = fd;

                        if (epoll_ctl(efd, EPOLL_CTL_MOD, fd, &ev) < 0)
                        {
                            printf("Couldn't modify client socket %d in epoll set: %m\n", fd);
                            goto cleanup;
                        }
                    }
                }
            }

            if (events & EPOLLIN)
            {
                if (fd == sd)
                {
                    while ((clientsd = accept(sd, (struct sockaddr *) &peeraddr, &salen)) < 0)
                    {
                        if ((clientsd < 0) && (errno != EINTR))
                        {
                            printf("Accept on socket %d failed: %m\n", sd);
                            goto cleanup;
                        }
                    }

                    if (inet_ntop(AF_INET, &peeraddr.sin_addr.s_addr, buffer, sizeof(buffer)) != NULL)
                    {
                        printf("Accepted connection from %s:%u, assigned new sd %d\n", buffer, ntohs(peeraddr.sin_port), clientsd);
                    } else
                    {
                        printf("Failed to convert address from binary to text form: %m\n");
                    }

                    ev.events = EPOLLIN;
                    //ev.data.u64 = 0LL;
                    //ev.data.fd = clientsd;
                    //((struct SessionData *) ev.data.ptr)->FileDescriptor = clientsd;
                    SessionData = malloc(sizeof(SessionData));
                    SessionData->FileDescriptor = clientsd;
    SessionData->Data1 = 1;
    SessionData->Data2 = 2;
    SessionData->Data3 = 3;
                    ev.data.ptr = SessionData;

                    if (epoll_ctl(efd, EPOLL_CTL_ADD, clientsd, &ev) < 0)
                    {
                        printf("Couldn't add client socket %d to epoll set: %m\n", clientsd);
                        goto cleanup;
                    }

                    pollsize++;
                    } else
                {
                    while ((rc = recv(fd, buffer, sizeof(buffer), 0)) < 0)
                    {
                        if ((fd < 0) && (errno != EINTR))
                        {
                            printf("Receive from socket %d failed: %m\n", fd);
                            pollsize--;
                            shutdown(fd, SHUT_RDWR);
                            close(fd);
                            continue;
                        }
                    }

                    if (rc == 0)
                    {
                        printf("Closing socket with sd %d\n", fd);
                        pollsize--;
                        shutdown(fd, SHUT_RDWR);
                        close(fd);
                        continue;
                    } else if (rc > 0)
                    {
                        //printf("Received '");
                        //printf("Received '");
                        //printf("Received '");
                        //printf("Received '");
                        //printf("Received '");
                        printf("Received '");
                        sprint_buffer(buffer, rc);
                        printf("' from socket with sd %d\n", fd);

                        ev.events = EPOLLIN | EPOLLOUT;
                        //ev.data.u64 = 0LL;
                        //ev.data.fd = fd;
            //            ((struct SessionData *) ev.data.ptr)->FileDescriptor = fd;

                        if (epoll_ctl(efd, EPOLL_CTL_MOD, fd, &ev) < 0)
                        {
                            printf("Couldn't modify client socket %d in epoll set: %m\n", fd);
                            goto cleanup;
                        }
                    }
                }
            }
        }
    }

cleanup:
    shutdown(sd, SHUT_RDWR);
    close(sd);

    return ;

 

We Also Found This Discussion For You

1. Web Development

Intersection and union of array by hash

Hi, A piece of script from Perl-cookbook I do not understand, and post here for explanation. The purpose is to find the element in either array (union), and in both array (intersection). Thank you in advance. @a=qw(1 3 5 6 7 8); @b=qw(2 3 5 7 9); foreach $e (@a, @b) {$union{$e}++ &&... (3 Replies)
Discussion started by: yifangt
3 Replies
All times are GMT -4. The time now is 02:54 PM.
Unix & Linux Forums Content Copyright 1993-2022. All Rights Reserved.
Privacy Policy