Antoun
Antoun

Reputation: 137

C pipe multiple message only one recieved

I am trying to send two messages from the parent to the receiver. Only one is received. Receiver uses stdin and stdout for the pipe, and outputs its results into std err. Here is my code.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>

int main(int argc,char * argv[])
{
    char buffer[100]; // The pipe's buffer
    int pipes[2];

    pid_t   childpid;

    if ( pipe(pipes) ){
        fprintf(stderr,"FATAL ERROR IN PIPE");
    }


    if((childpid = fork()) == -1){
            perror("fork");
            exit(1);
    }

    if(childpid == 0){
        close(pipes[1]);

        dup2(pipes[0],STDIN_FILENO);

        scanf("%s\n",buffer);
        fprintf(stderr,"REC: %s\n",buffer);
        scanf("%s\n",buffer);
        fprintf(stderr,"REC: %s\n",buffer);
        sleep(50);
    }
    else
    {
        close(pipes[0]);

        // Read in a string from the pipe 
        char* arr = "HelloWorld\n";
        write(pipes[1],arr,strlen(arr)+1);
        write(pipes[1],arr,strlen(arr)+1);  
        sleep(50);
    }
    return 0;   
}

Upvotes: 4

Views: 1022

Answers (2)

P.W
P.W

Reputation: 26800

One problem is with the following line:

scanf("%s\n",buffer);

scanf does not read trailing white space (including new-line characters) unless matched by a directive. But the directive exists here. So it waits for another new line after the usual new line which follows the input.

Remove the \n in both the scanf statements.

Secondly, you have to modify your fprintf statements to add the \n in them.

fprintf(stderr,"REC: %s\n",buffer);

Thirdly, don't add 1 to the strlen(arr) in write. Modify it to:

write(pipes[1],arr,strlen(arr));

It works. See live demo:

Output:

REC: HelloWorld
REC: HelloWorld

Real time: 2.082 s
User time: 0.043 s
Sys. time: 0.037 s
CPU share: 3.85 %
Exit code: 0

Upvotes: 0

Petr Skocik
Petr Skocik

Reputation: 60107

The problem is the strlen(arr)+1 part. You're sending the terminating nul as well and that nul ends up making up the second "string" read by scanf:

REC: HelloWorld
REC: 

If you remove the +1, you'll get both lines (I've also decreased the sleep times because I'm not patient enough to wait 50 seconds for the result):

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>

int main(int argc,char * argv[])
{
    char buffer[100]; // The pipe's buffer
    int pipes[2];

    pid_t   childpid;

    if ( pipe(pipes) ){ fprintf(stderr,"FATAL ERROR IN PIPE"); }
    if((childpid = fork()) == -1){ perror("fork"); exit(1); }

    if(childpid == 0){
        close(pipes[1]);

        dup2(pipes[0],STDIN_FILENO);

        scanf("%s\n",buffer);
        fprintf(stderr,"REC: %s\n",buffer);
        scanf("%s\n",buffer);
        fprintf(stderr,"REC: %s\n",buffer);
        sleep(2);
    }
    else
    {
        close(pipes[0]);

        // Read in a string from the pipe 
        char* arr = "HelloWorld\n";
        write(pipes[1],arr,strlen(arr)); // << NO +1 
        write(pipes[1],arr,strlen(arr)); // << NO +1
        sleep(2);
    }
    return 0;   
}

Upvotes: 3

Related Questions