Что делает autoflush в сокете? Почему мы используем это?

Я работаю над кодом сокета и не могу понять, почему autoflush используется на сокете. Это как то так

my $sock = IO::Socket::Unix(Peer => $socketfilename , Type => SOCK_STREAM)

autoflush $sock 1;

Также есть места с

autoflush STDERR 1

autoflush STDOUT 1

для общего filehnadles.

Что оно делает? И что произойдет или произойдет, если я не буду использовать это? Пожалуйста, приведите несколько практических примеров, чтобы я понял, а не простое определение.

3 ответа

Данные обычно не отправляются сразу в сокет, они буферизуются до определенной точки, а затем отправляются сразу.

Автоматическая очистка означает, что данные проходят прямо через буфер, а затем сбрасываются, а не хранятся в буфере в ожидании поступления и накопления других данных.

Так просто.

Без автоматической промывки:

Tick | DATA sent|Socket Buffer| DATA received
.....|..........|.............|..............
1    | XX       | XX          | (nothing)
2    | yy       | yyXX        | (nothing)
3    | ZZZ      | ZZZyyXX     | (nothing)
4    | t        | (empty)     | tZZZyyXX

С автоматической промывкой:

Tick | DATA sent | Socket Buffer | DATA received
.....|...........|...............|..............
1    | XX        | ()            | XX
2    | yy        | ()            | yy
3    | ZZZ       | ()            | ZZZ
4    | t         | ()            | t
  • Размер буфера: 8 символов
  • Очень простой пример, вы можете поднять некоторые другие вопросы, увидев его - большая его часть также зависит от реализации. Более того, буферизация может происходить на разных уровнях (отправитель, получатель, приложение и т. Д.)

Это абсолютно ничего не делает... потому что IO::Socket::Unix уже делает это для вас.

Нагрузка на отправку данных кусками меньше, поэтому библиотеки файлов накапливают данные для печати в буфере, а не отправляют их в систему немедленно. Только когда накоплено 4 КБ или 8 КБ (в зависимости от версии) данных, данные фактически отправляются в систему. Это называется "буферизацией".

Установка для autoflush значения true для дескриптора отключает буферизацию для этого дескриптора. Когда вы звоните printданные отправляются в систему раньше print возвращается.

Увидеть разницу:

$ perl -e'
   STDOUT->autoflush($ARGV[0]);
   for (0..9) { print $_ x 1024; sleep 1; }
' 1
<whole bunch of 1s>
<one second later: whole bunch of 2s>
<one second later: whole bunch of 3s>
<one second later: whole bunch of 4s>
<one second later: whole bunch of 5s>
<one second later: whole bunch of 6s>
<one second later: whole bunch of 7s>
<one second later: whole bunch of 8s>
<one second later: whole bunch of 9s>

$ perl -e'
   STDOUT->autoflush($ARGV[0]);
   for (0..9) { print $_ x 1024; sleep 1; }
' 0
# Before Perl 5.14:
<four seconds later: whole bunch of 0s, 1s, 2s and 3s>
<four seconds later: whole bunch of 4s, 5s, 6s and 7s>
<two seconds later: whole bunch of 8s and 9s>
# Perl 5.14+
<eight seconds later: whole bunch of 0s, 1s, 2s, 3s, 4s, 5s, 6s and 7s>
<two seconds later: whole bunch of 8s and 9s>

autoflush включается IO::Socket::*, потому что это требуется в большинстве случаев для сокетов. Розетки часто используются для интерактивного общения. Запрос, ответ, запрос, ответ и т. Д. Представьте, что произойдет, если запрос застрянет в буфере... Вы будете ждать ответа вечно!

От IO:: Handle:

sub autoflush {
    my $old = new SelectSaver qualify($_[0], caller);
    my $prev = $|;
    $| = @_ > 1 ? $_[1] : 1;
    $prev;
}

Нет магии.

от:

$ |

Если установлено значение, отличное от нуля, принудительно сбрасывает сразу и после каждой записи или печати на выбранном в данный момент выходном канале. По умолчанию 0 (независимо от того, действительно ли канал буферизован системой или нет; $| говорит только, просили ли вы Perl явно сбрасывать после каждой записи). STDOUT обычно будет буферизоваться строкой, если вывод поступает на терминал, а блок буферизован иначе. Установка этой переменной полезна в первую очередь, когда вы выводите данные в канал или сокет, например, когда вы запускаете Perl-программу из rsh и хотите видеть результат, как он происходит. Это не влияет на буферизацию ввода. Смотрите getc для этого. См. О том, как выбрать выходной канал. Смотрите также IO:: Handle.

Другие вопросы по тегам