Question

all, I am designing a Key-Value server, and when I wrote the client, and I found a really strange thing,see the simplified code:

while(1)
{
    printf("->:");
    read(STDIN_FILENO, buf, sizeof(buf));
    write(client_sock, buf, sizeof(buf));
    int m = read(client_sock, buf, sizeof(buf));
    buf[m] = '\0';
    printf("%s", buf);
}

when I run the program, it first ask for input, so I input something, but nothing happen! (the server runs well, and it well echo something, when I use other client)

then I change the code only one line:

printf("\n->:");

then it runs well! why? why "\n" can change the output? I guess it maybe the read() , but I can't explain it

Was it helpful?

Solution

printf(3) is part of the C standard IO library, which performs internal buffering to provide performance improvements.

There are three types of buffering: none, line, and block.

Which buffering is applied is determined in part by whether the descriptor being written to is 2 or not, and if it is connected to a terminal. (See isatty(3).)

If the printing is done to stderr (2) then no buffering is done.

If the printing is done to any other descriptor, then the behavior changes if it is a terminal or not: if output is a terminal, then the output is line buffered. If the output is not a terminal (file, pipe, socket, etc.) then the output is block buffered.

When line buffered, it waits for the \n before printing anything. (Or if you write enough to overflow the internal buffers before sending a \n.)

What I'd recommend instead is the following:

printf("->:");
fflush(stdout);
read(STDIN_FILENO, buf, sizeof(buf));
/* ... */
printf("%s\n", buf);

It's a small change; you won't get a pointless empty line at program start, and the prompt should show up .. promptly.

You can use the setvbuf(3) function to change the buffering for your stream once, at start up, and never need to flush it again, if you would rather.

int err = setvbuf(stdout, NULL, _IONBF, 0);
/* check err */

OTHER TIPS

Standard output is line-buffered by default. If you don't write a complete line, the output will be held in the buffer until you do. You can use fflush to flush the stream or setbuf to change the buffering mode.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top