Thread: fgets not working correctly

  1. #1
    Registered User
    Join Date
    Jan 2012

    fgets not working correctly

    There are two different programs, one is called SEND and one is called RECIEVE. The code for both of these was given and originally they communicated with each other using simplex communication (one way). The assignment was to implement half duplex communication (both ways, one at a time.) The code for RECIEVE is at [C] RECIEVE - The error is at line 175. I am running it using a linux terminal. Basically what happens is I'm able to send a message from SEND and RECIEVE notifies me that it got it and then I'm supposed to send a message back and it never gets past the fgets.
    Thats a screen shot of what I get when I run this program. The first line comes from the send program but the last two with red arrows pointing at them come from this program. As you can see it gets to the recieved line, and then outputs enter line2, and then nothing.
    My question is obviously, why won't fgets take my input and continue along with the program?

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    The edge of the known universe
    And for those who don't like reading white on white...
    /* This code is derived from the CMPS 376 networking code by Marc Thomas
     * The purpose of this code is to create a very simple Internet server which
     * binds to a port, does a simple handshake with the client and then echos
     * everything the client sends to the screen.
     * Command line usage:
     *   $ vcrec [packet_size] &
     *   if packet_size is specified, it must be a positive integer and only that
     *   many bytes will be read from the client.
     * TCP/IP socket functions used by this program:
     *   socket()        Create a byte stream for client connection requests
     *   bind()          Bind the socket to IP address and request TCP port number
     *   getsockname()   Query what port number the system assigned to the process
     *   listen()        Wait for a client to issue a connection request
     *   accept()        Accept the connection request from a client
     *   send()          Send data to the client
     *   recv()          Receive data from the client
     *   close()         Close the sockets
     * Connection process:
     * vcsend                      vcrec
     * -------------------------   -------------------------
     * socket() (client socket)    socket() (listen socket)
     *                             bind()
     *                             getsockname()
     *                             listen()
     * connect() --------------->  accept() (creates 2nd data socket)
     * (data exchange phase can be response-driven but if more
     *  than one descriptor must be managed use of select() is
     *  strongly recommended)
     * send() --------------------> recv()
     * recv() <-------------------- send()
     * close() (client socket)     close() (both data and listen socket)
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <sys/time.h>
    #include <unistd.h>      /* for gethostname() */
    #include <arpa/inet.h>   /* for IP address structures and functions */
    #include <netdb.h>
    int main(int argc, char *argv[], char *envp[])
            int     sock, msgsock;  /* Sockets are integer file descriptors on Linux */
            struct  sockaddr_in name, caller;
            struct  hostent *hp;
            char    buf[2048], chrline[80];
            int     size, length, ret, k, i; /* Process the command line for the buffer size, if given */
            if (argc > 1)
                    size = atoi(argv[1]);
        /* Validate that the given argument is between 1 and sizeof(buf) - 1
         * Set to the default size if argument is invalid */
                    if (size < 1  ||  size > sizeof(buf) - 1)
                            size = sizeof(buf) - 1;
                    size = sizeof(buf) - 1;  /* Default size */
      /* Create the listen socket. This is a TCP socket, so use SOCK_STREAM
       * Exit if the socket cannot be created */
            sock = socket(AF_INET, SOCK_STREAM, 0);
            if (sock < 0)
                    perror("receiver: socket() failed. ");
                    return (-1);
      /* Bind the socket to an IP address and port. We will use the IP address
       * INADDR_ANY, which tells the system to assign the IP address, and the
       * port number 0, which tells the system to assign a random port number.
       * First we have to set the fields in the sockaddr_in object "name" and then
       * we can call bind(). Again, exit if bind() fails. */
            name.sin_family = AF_INET;         /* TCP/IP family */
            name.sin_addr.s_addr = INADDR_ANY; /* INADDR_ANY = assigned by system */
            name.sin_port = htons(0);                /* 0 = assigned by system */
            ret = bind(sock,(struct sockaddr *)&name,sizeof name);
            if (ret < 0)
                    perror("receiver: bind() failed. ");
                    return (-1);
      /* In order to use vcsend to send data to this program, we need to know
       * what port number the system just assigned this program. So this segment
       * calls getsockname() to update the sockaddr_in object "name" with the
       * system assigned values and then print that info to the screen. */
            length = sizeof name;
            ret = getsockname(sock, (struct sockaddr *)&name, (socklen_t *)&length);
            if (ret < 0)
                    perror("receiver: getsockname() failed. ");
                    return (-1);
            sleep(1);       /* pause for clean screen display */
            printf("\nreceiver: process id: %d ", (int)getpid());
            printf("\nreceiver: IP address: %d.%d.%d.%d",
            (ntohl(name.sin_addr.s_addr) & 0xff000000) >> 24,
            (ntohl(name.sin_addr.s_addr) & 0x00ff0000) >> 16,
            (ntohl(name.sin_addr.s_addr) & 0x0000ff00) >>  8,
            (ntohl(name.sin_addr.s_addr) & 0x000000ff));
            printf("\nreceiver: port number: %hu", ntohs(name.sin_port));
      /* Now we will call listen() and wait for a client to connect. The
       * accept() function will block until there is a client or an error. */
            listen(sock,5);         /* up to 5 clients can connect. only 1st is accepted */
            k = sizeof caller;
            msgsock = accept(sock, (struct sockaddr *)&caller, (socklen_t *)&k);
      /* We only reach this point when there is an error or a client. We can
       * check the value of msgsock (the data socket) to see which has happened */
            if (msgsock == -1)
                    perror("receiver: accept() failed. ");
        printf("\nreceiver: Valid connection received.\n");
        printf("receiver: Sending handshake.\n");
                    /* let vcsend know we are ready by sending a single character */
              buf[0]= '0';
              send(msgsock, buf, 1, 0);
        printf("receiver: Waiting for client....\n");
              do    {
                            bzero(buf,sizeof buf);  /* zero buffer to remove old data */
          /* recv() will block until the client sends information, the client
           * closes the connection or an error occurs on the data socket. */
                            ret = recv(msgsock, buf, size, 0);
                            if (ret < 0)
                                    perror("receiver: recv() failed. ");
                            if (ret == 0)
                        printf("        received-->sender has ended connection \n");
                                    printf("        received-->%s \n",buf);
                            //recv(msgsock, chrline, sizeof(chrline) - 1, 0); /*Handshake character*/
                            printf("enter line2> ");
                            /* Read input from user */
                            fgets(chrline, sizeof(chrline) - 1, stdin);
                            printf("FINISHED fgets recieve");
                            /* Check for the period to end the connection and also convert any
                            * newlines into null characters */
                            for (i = 0 ; i < (sizeof(chrline) - 1) ; i++)
                             printf("entered for loop recieve");
                             if ( (chrline[i] == '\n') || (chrline[i] == '\0') )
                            if (chrline[i] == '\n')
                              printf("entered if loop1 recieve");
                              chrline[i] = '\0';    /* get rid of newline */
                            length = strlen(chrline);
                            if (chrline[0] == '.')          /* end of stream */
                              printf("entered if loop 2 recieve");
                              printf("sender: termination requested \n");
                              break; /* Exit out of loop */
                              ret = send(msgsock, chrline, length + 1, 0);
                            if (ret < 0)
                              perror("sender: write() failed. ");
                              break;  /* Exit out of loop */
                    } while (ret != 0); /* Exit loop only when client ends connection */
      /* When we exit the recv() loop, the client has ended the connection, so
       * all that remains is closing the sockets. */
            printf("receiver: ending session also and exiting. \n");
            close(msgsock);         /* close data socket */
            close(sock);      /* close listen socket */
            return (0);
    }  /* end of main */
    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
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    The edge of the known universe
    You should probably create another terminal, where you do
    in one window, and
    in another.

    Putting a process into the background and then trying to read stdin just isn't going to work.
    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.

  4. #4
    Registered User
    Join Date
    Nov 2010
    Long Beach, CA
    It's far more likely it's hanging on the send or recv call. None of your diagnostic printf calls (e.g. "FINISHED fgets receive") have a \n in them. stdout is line buffered meaning not every call to printf results in immediate output. Output is only sent to the terminal under the following conditions:

    1. There is a new line in what you print
    2. You explicitly call fflush(stdout)
    3. You request input from stdin (e.g. fgets, scanf, etc)

    After fgets reads your "hello" the second time, your code never does one of those three things to cause output to print, hence you think it's hanging on the fgets. I suspect adding a \n to those printfs would cause it to actually print several of those lines out and show where it's actually hanging.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 7
    Last Post: 12-09-2010, 03:22 PM
  2. Max/min function not working correctly
    By En-Motion in forum C++ Programming
    Replies: 6
    Last Post: 03-19-2009, 12:28 AM
  3. Pointers are not working correctly
    By adrian_fpd in forum C Programming
    Replies: 8
    Last Post: 11-17-2008, 06:55 PM
  4. function not working correctly
    By mackieinva in forum C Programming
    Replies: 0
    Last Post: 09-29-2007, 08:22 PM
  5. File I/O not working correctly
    By gL_nEwB in forum C++ Programming
    Replies: 4
    Last Post: 05-27-2006, 10:29 PM