Thread: selct()

  1. #1
    Registered User
    Join Date
    Jan 2011
    Posts
    6

    selct()

    Hi,
    What's worng here. My select() call always return 0. Here my parent is the server and child is the client. My select() call is in the server process.
    Code:
    while (1) {
        printf("----------Inside select()\n");
        sel = select(sockfd, &read_fd, NULL, NULL, &timeout);
        FD_SET(sockfd, &read_fd);
        if (sel > 0) {
            if (FD_ISSET(sockfd, &read_fd)) {
                clilen = sizeof(clientAdd);
                if ( (newsockfd = accept(sockfd, (struct sockaddr *)&clientAdd, &clilen) < 0)){
                    printf("ERROR SERVER: Accept() failed\n");
                    exit(1);
                }
                //make child process
                printf("forking now\n");
                pid = fork();
                if (pid < 0) {
                    perror("fork");
                    exit(1);
                }
                if (pid == 0) { //child process
    
                    printf("this is the child\n");
                    // The sockfd has data to be read
                    close(sockfd);
                    n = read(newsockfd, buffer, 255);
                    printf("received size: %d\n", n);
                    printf("%s\n", buffer);
                    close(newsockfd);
                } else {        //parent process
                    printf("This is the parents\n");
                    close(newsockfd);
                }
                } else {
                    printf("FD_ISSET() did not set\n");
                }
            }else if (sel < 0) {
                /* An error ocurred, just print it to stdout */
                perror("select");
            } else if (sel == 0) {
                printf("select is returnig 0\n\n");
                break;
            }
        }

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > sel = select(sockfd, &read_fd, NULL, NULL, &timeout);
    Quote Originally Posted by man page
    nfds is the highest-numbered file descriptor in any of the three sets,
    plus 1.
    If sockfd is the only thing set in read_fd, then it will always return 0.

    Try sockfd+1
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Jan 2011
    Posts
    6
    Thank U for the reply.................. But I have tried sockfd+1 as U have said. It always returning 0

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > FD_SET(sockfd, &read_fd);
    Why is this AFTER your select call?
    I think your set is actually empty.

    How did you set up timeout?
    If you're on Linux, then note this from the manual page
    "On Linux, select() modifies timeout to reflect the amount of time not slept;"

    Did you FD_ZERO your set before you started?

    Post some of the code leading up to your select call - context is important.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Jan 2011
    Posts
    6
    Thank again for U R reply. Here is the code before while(1)
    Code:
    fd_set read_fd;
        struct timeval timeout;
        timeout.tv_sec = 5;
        timeout.tv_usec = 0;
        FD_ZERO(&read_fd);
    
        pid_t pid;
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
    
        printf("----------serverProcess Running-------\n");
    
        if (sockfd < 0) {
            printf("serverProcess ERROR: Opening Socket\n");
            exit(0);
        }
        bzero((char *) &serverAdd, sizeof(serverAdd));
        serverAdd.sin_family = AF_INET;
        serverAdd.sin_addr.s_addr = INADDR_ANY;
        serverAdd.sin_port = htons(portno);
        if (bind(sockfd, (struct sockaddr *) &serverAdd,sizeof(serverAdd)) < 0) {
            printf("serverProcess ERROR: on Binding\n");
            pid = getpid();
            kill(pid1, SIGKILL); // Kill my child(client) process
            exit(0);
        }
        listen(sockfd,1);

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Firstly, it is "your", not "U R"

    So I see I was right then, you don't correctly initialise your set.

    Do this
    Code:
    while ( 1 ) {
        fd_set read_fd;
        struct timeval timeout;
        timeout.tv_sec = 5;
        timeout.tv_usec = 0;
        FD_ZERO(&read_fd);
        FD_SET(sockfd, &read_fd);
        sel = select(sockfd+1, &read_fd, NULL, NULL, &timeout);
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Jan 2011
    Posts
    6
    Thank You for your Reply. But still its returning ZERO. I debugged using gdb. The sel value is more than ZERO.
    Code:
    131         FD_SET(sockfd, &read_fd);
    (gdb)
    133             printf("----------Inside select()\n");
    (gdb)
    ----------Inside select()
    134             sel = select(sockfd, &read_fd, NULL, NULL, &timeout);
    (gdb) print sel
    $1 = 5861952
    (gdb)
    $2 = 5861952
    (gdb) n
    135             if (sel > 0) {
    (gdb)
    165                     }else if (sel < 0) {
    (gdb) print sel
    $3 = 0
    You can check here. At line number 134 the sel value is 5861952 which is greater than ZERO. So it should go to line number 136 onwards. But its not going there.
    I tried declaring sel as unsigned int since its value is too large. But still its returning ZERO.

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > At line number 134 the sel value is 5861952 which is greater than ZERO
    At line 134, sel is garbage because you haven't called select() yet to get a return value assigned.

    Try say
    int sel = 11223344;
    ....
    sel = select(sockfd, &read_fd, NULL, NULL, &timeout);
    and then step through with gdb.

    If you've only got 1 descriptor set in your fd sets, then the only possible values select can return are
    -1 => error
    0 => no fd's ready
    1 => the fd you set is ready.

    The print at line 165 is the assigned value, which is zero.

    And you're still not doing +1 on the first parameter to select.

    Post your latest code.
    I see you moved the FD_SET(), I'm wondering what else you have done.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  9. #9
    Registered User
    Join Date
    Jan 2011
    Posts
    6
    Here is my complete code.............. Please do help
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #define portno 3386
    
    void clientProcess(char *argv[]) {
            extern LABEL;
            int sockfd,n;
            struct sockaddr_in serverAdd;
            struct hostent *server;
            char buffer[256];
            // Create Socket
            sockfd = socket(AF_INET, SOCK_STREAM, 0);
            if (sockfd < 0) {
                    printf("clientProcess ERROR: Socket Not Created");
            }
            server = gethostbyname("127.0.0.1");//argv[1]);
            if (server == NULL) {
                    printf(" No such HOST\n");
                    exit(0);
            }
            bzero((char *) &serverAdd, sizeof(serverAdd));
            serverAdd.sin_family = AF_INET;
            bcopy((char *)server->h_addr,(char *)&serverAdd.sin_addr.s_addr,server->h_length);
            serverAdd.sin_port = htons(portno);
    
            if (connect(sockfd,(const struct sockaddr *)&serverAdd,sizeof(serverAdd)) < 0) {
                    printf("clientProcess ERROR : NO Connect\n");
                    exit(0);
            }
            printf("-----------Inside clientProcess-------------\n\n");
            printf("Please enter the message: ");
            bzero(buffer,256);
            fgets(buffer,255,stdin);
            n = write(sockfd,buffer,strlen(buffer));
            if (n < 0) {
                    printf("clientProcess ERROR: Writing \n");
            }
            bzero(buffer,256);
            close(sockfd);
    }
    
    void serverProcess(char *argv[], int pid1) {
    
            int sockfd, newsockfd, clilen, n;
            int sel, i;
            char buffer[256];
            struct sockaddr_in serverAdd, clientAdd;
    
            fd_set active_fd, read_fd;  // two fd's
            struct timeval timeout;
            timeout.tv_sec = 5;
            timeout.tv_usec = 0;
    
            FD_ZERO(&active_fd); // set zero for active_fd
            FD_SET(sockfd, &active_fd);
    
            pid_t pid;
            sockfd = socket(AF_INET, SOCK_STREAM, 0);
    
            printf("----------serverProcess Running-------\n");
    
            if (sockfd < 0) {
                    printf("serverProcess ERROR: Opening Socket\n");
                    exit(0);
            }
            bzero((char *) &serverAdd, sizeof(serverAdd));
            serverAdd.sin_family = AF_INET;
            serverAdd.sin_addr.s_addr = INADDR_ANY;
            serverAdd.sin_port = htons(portno);
            if (bind(sockfd, (struct sockaddr *) &serverAdd,sizeof(serverAdd)) < 0) {
                    printf("serverProcess ERROR: on Binding\n");
                    pid = getpid();
                    kill(pid1, SIGKILL);
                    exit(0);
            }
            listen(sockfd,1);
            while (1) {
                    read_fd = active_fd;
                    sel = select(sockfd+1, &read_fd, NULL, NULL, &timeout);
                    if(sel < 0) {
                            printf("select ERROR\n");
                    }
                    for(i = 0; i< (sockfd+1); i++) {
                            if (FD_ISSET(i, &read_fd))      {
                                    if(i == sockfd) {
                                            clilen = sizeof(clientAdd);
                                            if ( (newsockfd = accept(sockfd, (struct sockaddr *)&clientAdd, &clilen) < 0)){
                                                    printf("ERROR SERVER: Accept() failed\n");
                                                    exit(1);
                                            }
                                    } else {
                                            //make child process
                                            printf("forking now\n");
                                            pid = fork();
                                            if (pid < 0) {
                                                    perror("fork");
                                                    exit(1);
                                            }
                                    if (pid == 0) { //child process
                                                    printf("this is the child\n");
                                                    // The sockfd has data to be read
                                                    close(sockfd);
                                                    n = read(newsockfd, buffer, 255);
                                                    printf("received size: %d\n", n);
                                                    printf("%s\n", buffer);
                                                    close(newsockfd);
                                            } else {                //parent process
                                                    printf("This is the parents\n");
                                                    close(newsockfd);
                                            }
                            }
                            }
                    }
            }
            close(newsockfd);// Close accepct descriptor
            close(sockfd); // Close socket descriptor
    }
    
    int main(int argc, char *argv[]) {
        int pid1, pid2;
        if(argc < 1) {
            printf("USEAGE: ./socket <portno> <localhost>\n");
            exit(0);
        }
        pid1 = fork();
        if(pid1 > 0) {
            serverProcess(argv, pid1);
        } else {
            sleep(3);
            clientProcess(argv);
        }
        return (0);
    }
    Last edited by India; 02-08-2011 at 01:04 AM.

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Maybe compile with some warnings.
    Code:
    $ gcc -Wall bar.c
    bar.c: In function ‘clientProcess’:
    bar.c:12: warning: type defaults to ‘int’ in declaration of ‘LABEL’
    bar.c:40: warning: implicit declaration of function ‘write’
    bar.c:45: warning: implicit declaration of function ‘close’
    bar.c:12: warning: unused variable ‘LABEL’
    bar.c: In function ‘serverProcess’:
    bar.c:78: warning: implicit declaration of function ‘getpid’
    bar.c:93: warning: pointer targets in passing argument 3 of ‘accept’ differ in signedness
    /usr/include/sys/socket.h:214: note: expected ‘socklen_t * __restrict__’ but argument is of type ‘int *’
    bar.c:100: warning: implicit declaration of function ‘fork’
    bar.c:109: warning: implicit declaration of function ‘read’
    bar.c: In function ‘main’:
    bar.c:135: warning: implicit declaration of function ‘sleep’
    bar.c:126: warning: unused variable ‘pid2’
    bar.c: In function ‘serverProcess’:
    bar.c:61: warning: ‘sockfd’ is used uninitialized in this function
    
    Do you see what is wrong here?
    Code:
            FD_ZERO(&active_fd); // set zero for active_fd
            FD_SET(sockfd, &active_fd);
    
            pid_t pid;
            sockfd = socket(AF_INET, SOCK_STREAM, 0);
    I said this a week ago, it's getting old.


    Also, check your indent style. It might look indented, but it isn't reflecting the program flow you intend.
    Code:
                    if (i == sockfd) {
                        clilen = sizeof(clientAdd);
                        if ((newsockfd =
                             accept(sockfd, (struct sockaddr *) &clientAdd,
                                    &clilen) < 0)) {
                            printf("ERROR SERVER: Accept() failed\n");
                            exit(1);
                        }
                    } else {
                        //make child process
                        printf("forking now\n");
                        pid = fork();
                        if (pid < 0) {
                            perror("fork");
                            exit(1);
                        }
                        if (pid == 0) { //child process
                            printf("this is the child\n");
                            // The sockfd has data to be read
                            close(sockfd);
                            n = read(newsockfd, buffer, 255);
                            printf("received size: %d\n", n);
                            printf("%s\n", buffer);
                            close(newsockfd);
                        } else {    //parent process
                            printf("This is the parents\n");
                            close(newsockfd);
                        }
                    }
    Surely you mean to create a new process on the accept right?

    Perhaps you need to use a function, so you can keep a better track of the scope of things.
    Like
    Code:
    if (i == sockfd) {
        spawnReaderThread();
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed