1
void async_socket_rcv(int clientfd);

int main(int argc, char *argv[])
{
    //Configure buffer to output immediately
    setvbuf(stdout, 0, _IONBF, 0);

    //Mysql version
    printf("MySQL client version: %s\n", mysql_get_client_info());

    //Initialize the FDs for the sockets
    int socketfd, clientfd;

    //Initialize the list of FDs to monitor for input
    fd_set fd_monitor;
    int select_res;
    FD_ZERO(&fd_monitor);

    struct timeval select_timeout;
    select_timeout.tv_sec = 3;
    select_timeout.tv_usec = 0;


    //Initialize the thread id
    pthread_t thread;

    ...

    //Create the listen socket
    socketfd = create_inet_server_socket("0.0.0.0", "5671", LIBSOCKET_TCP, LIBSOCKET_IPv4, 0);

    if(socketfd < 0){
        printf("Error creating listen socket!");
        return -1;
    }else{
        printf("Listening...");
    }

    FD_SET(socketfd, &fd_monitor);
    //FD_SET(STDIN_FILENO, &fd_monitor);

    while(1)
    {
        select_res = select(sizeof(fd_monitor) * 8, &fd_monitor, NULL, NULL, &select_timeout);

        if(FD_ISSET(socketfd, &fd_monitor))
        {
            clientfd = accept_inet_stream_socket(socketfd,0,0,0,0,0,0);
            pthread_create(&thread, NULL, async_socket_rcv, clientfd);
        }
        select_timeout.tv_sec = 3;
        select_timeout.tv_usec = 0;
    }

    return 0;

}

Hello all

I am trying to use the select() function to call a function when a client connects without having to block on the accept() function. I need to be able to accept stdin without interrupting the server.

My code above works, but only once. When I step through the code, i can see that select_res is 1 only if I connect to the server within the first iteration of select(). After that, nothing happens.

I'm sure one of you will spot some small error on my part, but for the life of me I can't see what I did wrong...

Matthew Goulart
  • 2,873
  • 4
  • 28
  • 63

2 Answers2

4

select alters the passed in fd_sets, setting the descriptors that have activity and unsetting those that don't. Since you don't reset fd_monitor in your loop, you used the altered fd_set.

Move the FD_ZERO and FD_SET calls to the beginning of the loop.

Colonel Thirty Two
  • 23,953
  • 8
  • 45
  • 85
  • Thank you sir! I must have read it 20 times... "On return, each of the input sets is modified to indicate the subset of descriptions that are ready." Sorry it didn't make it to the old melon :) – Matthew Goulart Sep 15 '15 at 17:46
0

While the answer above is 100% correct, it actually illustrates why using select() now smeels like 18th century. There is a wonderful poll(), which when used, would save you from all your troubles!

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • I can't remember where, but i seem to remember reading that poll was more costly than select. True? This server will be running on a raspberry pi – Matthew Goulart Sep 15 '15 at 17:50
  • I have never heard of poll being costlier than select. There is that quirk that select allows to specify timeouts in nanoseconds (through timeval), but poll only gives you miliseconds. But this is not the delay, this is maximum wait timeout. Other than that, I am not aware of any benefits of select over poll. – SergeyA Sep 15 '15 at 17:58
  • Are you aware of any benefits, other than simplicity, of poll over select? – Matthew Goulart Sep 15 '15 at 23:08
  • @MatthewGoulart From what I've gathered, `select` is an older interface and didn't scale as well, which led to the creation of `poll`. See also [What are the differences between poll and select?](http://stackoverflow.com/questions/970979/what-are-the-differences-between-poll-and-select) – Colonel Thirty Two Sep 16 '15 at 00:52
  • @MatthewGoulart, your whole question clearly indicates one of them :) Since poll() returns affected descriptors separately from subscribed, you do not need to re-init them, and the problem above simply would not happen! Imagine hours saved on debugging. – SergeyA Sep 16 '15 at 13:04
  • True. Although I do like the readability of select(). Now that I know how it works it's easy to follow the code. I'll stick with select but keep poll in mind for future projects. Thanks! – Matthew Goulart Sep 16 '15 at 13:27