Take the 2-minute tour ×

I used a simple fork() to simulate client / server then a very simple pipe to send / receive a char buffer of max 30 length, but it ends up printing non printable characters (small "?" and a box with 4 ones and zeroes) AFTER the desired word.

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

int main () {
    int pipefd[2];
    int cpid;
    char buf[31];
    if (pipe(pipefd) == -1) {
    cpid = fork();
    if (cpid == -1) P
    if (cpid == 0) {      // child reads from pipe
        close (pipefd[1]); // close unused write end
        read (pipefd[0], &buf, 30); // if I use 30 instead of strlen(buf) it prints Server transmit: Server receives. It does not wait for write. Makes no sense
        printf ("Server receives: %s", buf);
        close (pipefd[0])l
        exit (EXIT_SUCCESS);
    else {               // parent writes to pipe
        close (pipefd[0]); // closing unused read end;
        char buf2[30];
        printf("Server transmits: ");
        scanf ("%s", buf2);
        write (pipefd[1], buf2, strlen(buf2));
  return 0;

Also if I write more than one word it forgets about the second. In c++ I used getline (cin, string) but that's not an option here.

Also used read (pipefd[0], &buf, sizeof(buf));, now it prints in the correct order (no idea why strlen did not work) but I still get non printable characters at the end.

share|improve this question

1 Answer 1

up vote 3 down vote accepted

When you write (pipefd[1], buf2, strlen(buf2)); You neglect to put the '\0' in the stream. Change that to:

write (pipefd[1], buf2, strlen(buf2)+1);

And your string will now contain the null terminator, preventing the garbage at the end.

Using read (pipefd[0], &buf, strlen(buf)) did not work because buf is uninitialized. strlen is a simple function which looks for the terminating null at the end on the string, stopping when it's found. Unlike the length functions of C++ vectors, C functions have no way of accessing memory metadata. (sizeofis an operator)

share|improve this answer
Now I feel awful because I sorta already knew that, just ... missed it. But now. how can I read more than 1 word ? –  Kalec Jun 8 '12 at 4:19
Put read and write in loops. –  Dave Jun 8 '12 at 4:20
Doesn't this create the chance of an overflow ? or how can I specify when to end the loop ? could you give me a simple example ? I know I can while (read(pipefd[0], &buf, 1) > 0) and then make a counter. Let me try it out –  Kalec Jun 8 '12 at 4:26
@Kalec, that's really a separate question. Since you don't move your buffers, there's no risk of overflow. Try putting loops around the chunks of code that deal with reading and writing. Then, if you get stuck, post another question about where. –  Dave Jun 8 '12 at 4:29
@Kalec, don't I feel silly. When you said "more than one word" you meant literally that multi-word inputs were being truncated. I thought you meant that your server was only reading one chunk, then exiting. fgets does indeed fix your problem, and no looping is required for single-phrase transfer. –  Dave Jun 8 '12 at 5:31

Your Answer


