2013-02-22 3 views
4

Я работаю над кодом сокета и не могу понять, почему в соке есть autoflush. Это что-то вроде этогоЧто делает автофлюш в розетке? Почему мы используем это?

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

autoflush $sock 1; 

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

autoflush STDERR 1 

autoflush STDOUT 1 

для общего filehnadles.

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

+0

Очень странно способ написания '$ sock-> AutoFlush (1)', 'STDOUT-> AutoFlush (1)', и т.д. – ikegami

ответ

6

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

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

Как простой.

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

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 символов
  • Очень простой пример, вы можете поднять некоторые другие вопросы после видя это - большая часть его также зависит от реализации. Более того, буферизация может происходить на разных уровнях (отправитель, получатель, приложение и т. Д.)
5

Это абсолютно ничего не значит ... потому что 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 :: * потому, что это необходимо в большинстве случаев для сокетов. Розетки часто используются для интерактивной связи. Запрос, ответ, запрос, ответ и т. Д. Представьте, что произойдет, если запрос застрял в буфере .... Вы будете ждать ответа навсегда!

3

От IO::Handle:

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

Нет магии.

from:

$ |

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

+0

бы размещать простые текстовые ссылки из-за репутации, жаль об этом. – wat