Sponsored Content
Top Forums Programming Event driven programming / epoll / typedef union / session data array Post 302918101 by John S. on Sunday 21st of September 2014 01:28:14 PM
Old 09-21-2014
Resolved!

First let me credit this post by sachin...
c++ - How to use epoll_event data.ptr - Stack Overflow

which pointed out..
"The void *ptr and int fd both are inside a union inside the struct epoll_event. You should use either of them not both. Hence in your struct, add the field for fd as well and only link pointer to the struct in the ptr field of the epoll_event. This way when you get back your pointer then get the fd from it for further use."

In retrospect, it's all perfectly obvious, isn't it?

Here's what I added and edited...


I created a SessionData structure
Code:
struct SessionData
{
    int FileDescriptor;
    int Data1;
    int Data2;
    int Data3;
};

I ended up incrementing Data1 rather than rotating them to confirm operation as I desired. It's all good as they say.



There are six places where I modified Lrrr's original code.
Code:
    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;

I commented out the original code to set the data value to the file descriptor since I wanted to use the pointer value. I don't need the data 1, 2, and 3 values here because this is the SERVER socket. Indeed there is NO session data for the server socket, but since the event loop treats all sockets the same, I had to use a session data record.


Code:
        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;

Here is the start of the event handling loop. I now get the fd value from the session data structure.



Code:
                        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;

Here, for some not-yet-clear reason, Lrrr moves fd BACK to where it had recently been taken FROM. I have dutifully modified it to use the session data structure.


Code:
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;

Here is where a new client has connected. This is where the SessionData is needed. A new structure is malloc'd. I have yet to free this so I currently have a memory leak and will fix that next.


Code:
                        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;

Here again, fd is being copied back to where it came from a few moments earlier. I still do not see the need for this.



Code:
            if (events & EPOLLOUT)
            {
                if (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 ++);

Here I appended the output to expose the changing session data. Opening two telnet sessions showed the Data1 value incrementing and doing so independently for either session.



I also implemented a 10,000 msec (10 sec) timeout.
Code:
        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;
        }

I guess I am missing something to rationalize the use of the union type versus a structure so if anyone has an explanation regarding that, I'd be keen to hear it.

Cheers!

Last edited by John S.; 09-21-2014 at 02:34 PM.. Reason: Pasted wrong code.
 

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 03:39 PM.
Unix & Linux Forums Content Copyright 1993-2022. All Rights Reserved.
Privacy Policy