Search code examples
csocketstcpio

Working with buffered put and get, ensuring client gets info it needs before blocking call


I have a simple setup of a server and client, using TCP. The program consists of a client that asks a user to write a word into stdin. The client then reads the input, and sends it to the server to calculate the length of that string. The length is then returned back to the client, to be printed out to the user in stdout.

The problem I have is that after the server calculates the length, and sends it back to the client, the client is stuck on the fgets call, and doesn't read any of the new info put by the server. It is only after the server exits that the client is able to get the info that was put onto the file and print it out to the user.

Here's the segment of my server code that deals with the buffered input into the socket:

for (;;){
            if ((newSocketFD = accept(socketFD, NULL, NULL)) == -1){
                    perror("error occured while accepting");
                    continue;
            }
            printf("Accepted new connection\n");
            if (fork() == 0){
                    FILE *fp;
                    if ((fp = fdopen(newSocketFD, "r+")) == NULL){
                            perror("error opening file");
                            close(newSocketFD);
                            exit(1);
                    }
                    char *buffer;
                    buffer = (char *)malloc(sizeof(char)*1024);
                    while(fgets(buffer, 1024, fp) != NULL){
                            printf("server: string gotten - %s", buffer);
                            sprintf(buffer, "%ld", strlen(buffer)-1);
                            printf("the buffer is: %s\n", buffer);
                            fputs(buffer, fp); // client can't get any info from this command
                            fflush(fp);
                    }
                    free(buffer);
                    close(newSocketFD);
                    exit(0);
            }
    }

And here is the segment of my client code that deals with reading from stdin and sending the string to the server:

char * buffer = malloc(sizeof(char)*1024);
    for (;;){
            printf("Please enter a string:\n");
            if(fgets(buffer, sizeof(buffer), stdin) == NULL){
                    perror("reading string from stdin failed");
                    continue;
            }

            if(!(fputs(buffer, fp) > 0)){
                    perror("fput command failed");
                    continue;
            }
            fflush(fp);
            // client is stuck on the following line until the server exits
            if(fgets(buffer, 1024, fp) == NULL){
                    perror("error getting length of string. server not working.");
                    fclose(fp);
                    close(socketFD);
                    exit(1);
            }
            printf("The size of the string that was typed is: %d\n", atoi(buffer));
            fflush(stdout);
    }

I'm still a beginner to C, so this is mostly just practicing sockets for me. But I will appreciate any advice regarding the code. Thanks!


Solution

  • The client is using sizeof(buffer) when reading the user's input, but buffer is a char* pointer, so you are specifying the wrong buffer size and thus are not reading the full input, including the \n that the server's call to fgets() will be looking for to stop its reading.

    Change this:

    fgets(buffer, sizeof(buffer), stdin)

    To this:

    fgets(buffer, 1024, stdin)

    Also, the server is not sending a \n in its response, which the client's call to fgets() will be looking for to stop its reading.

    Change this:

    sprintf(buffer, "%ld", strlen(buffer)-1);

    To this:

    sprintf(buffer, "%ld\n", strlen(buffer)-1);