О read () в unistd.h (C ++) - PullRequest
       12

О read () в unistd.h (C ++)

1 голос
/ 18 декабря 2011

все, я проектирую сервер Key-Value, и когда я написал клиент и обнаружил действительно странную вещь, увидел упрощенный код:

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);
}

когда я запускаю программу, она сначала запрашивает ввод, поэтому я что-то ввожу, но ничего не происходит! (сервер работает хорошо, и он хорошо отображает что-то, когда я использую другой клиент)

тогда я изменяю код только одной строкой:

printf("\n->:");

тогда все работает хорошо! Зачем? почему "\ n" может изменить вывод? Я предполагаю, что это может быть чтение (), но я не могу объяснить это

Ответы [ 2 ]

5 голосов
/ 18 декабря 2011

printf(3) является частью стандартной библиотеки ввода-вывода C, которая выполняет внутреннюю буферизацию для повышения производительности.

Существует три типа буферизации: нет, строка и блок.

Какая буферизация применяется, частично определяется тем, является ли дескриптор для записи 2 или нет, и подключен ли он к терминалу. (См. isatty(3).)

Если печать выполняется в stderr (2), то буферизация не выполняется.

Если печать выполняется на любом другом дескрипторе, то поведение меняется, если это терминал или нет: если выходной сигнал - терминал, то на выходе будет строка с буферизацией . Если вывод не терминал (файл, канал, сокет и т. Д.), Тогда вывод будет с буферизацией блока .

Когда строка буферизована, она ждет \n, прежде чем что-либо печатать. (Или если вы напишите достаточно, чтобы переполнить внутренние буферы перед отправкой \n.)

Вместо этого я бы порекомендовал следующее:

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

Это небольшое изменение; вы не получите бессмысленную пустую строку при запуске программы, и подсказка должна появиться .. быстро.

Вы можете использовать функцию setvbuf(3), чтобы изменить буферизацию для вашего потока один раз, при запуске, и вам больше не придется очищать его снова, если вы предпочитаете.

int err = setvbuf(stdout, NULL, _IONBF, 0);
/* check err */
3 голосов
/ 18 декабря 2011

Стандартный вывод буферизован по умолчанию.Если вы не напишете полную строку, вывод будет храниться в буфере до тех пор, пока вы этого не сделаете.Вы можете использовать fflush для очистки потока или setbuf для изменения режима буферизации.

...