Что делает 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.