简体   繁体   English

autoflush在socket中做什么?我们为什么用它?

[英]What does autoflush do in socket? why do we use it?

I am working on some socket code and unable to figure out why there is autoflush used on socket. 我正在研究一些套接字代码,无法弄清楚为什么在socket上使用autoflush It is something like this 就是这样的

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

autoflush $sock 1;

Also there are places with 还有一些地方

autoflush STDERR 1

autoflush STDOUT 1

for general filehnadles. 对于一般filehnadles。

What does it do? 它有什么作用? Also what happens or will happen if I don't use it? 如果我不使用它会发生或将会发生什么? Please give some practical example so that I will understand rather than simple definition. 请举一些实际的例子,以便我理解而不是简单的定义。

Data doesn't usually get sent right away on the socket, it is buffered up to a certain point and then sent all-at-once. 数据通常不会立即在套接字上发送,它会被缓冲到某个点,然后一次性发送。

Auto-flushing means data goes right through the buffer and then flushed out, not kept in the buffer waiting for other data to arrive and accumulate. 自动刷新意味着数据直接通过缓冲区然后刷新,而不是保留在缓冲区中等待其他数据到达和累积。

As simple as that. 就如此容易。

Without auto-flush: 没有自动刷新:

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

With auto-flush: 使用自动刷新:

Tick | DATA sent | Socket Buffer | DATA received
.....|...........|...............|..............
1    | XX        | ()            | XX
2    | yy        | ()            | yy
3    | ZZZ       | ()            | ZZZ
4    | t         | ()            | t
  • Socket Buffer size: 8 chars 套接字缓冲区大小:8个字符
  • Very simple example, you might raise some other questions after seeing it - a big part of it is also implementation-dependent. 很简单的例子,你可能会在看到它之后提出一些其他问题 - 其中很大一部分也是依赖于实现的。 Moreover, buffering can happen at various levels (sender, receiver, application, etc.. ) 此外,缓冲可以发生在各个级别(发送者,接收者,应用程序等)。

It does absolutely nothing ...because IO::Socket::Unix already does it for you. 它绝对没有...因为IO :: Socket :: Unix已经为你做了。

There's less overhead to send data in chunks, so file libraries accumulate data to print in a buffer instead of sending to the system immediately. 以块的形式发送数据的开销较少,因此文件库会累积数据以在缓冲区中打印,而不是立即发送到系统。 Only when 4KB or 8KB (depending on the version) of data has been accumulated is the data actually sent to the system. 只有当累积了4KB或8KB(取决于版本)数据时,才会将实际发送到系统的数据。 This is called "buffering". 这称为“缓冲”。

Setting autoflush to true for a handle disables buffering for that handle. 将句柄的autoflush设置为true会禁用该句柄的缓冲。 When you call print , the data is sent to the system before print returns. 当您调用print ,数据将在print返回之前发送到系统。

See the difference: 看到不同:

$ 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 is turned on by IO::Socket::* because it's needed most of the times for sockets. IO :: Socket :: *打开了autoflush因为套接字大部分时间都需要它。 Sockets are often used for interactive communication. 套接字通常用于交互式通信。 Request, reply, request, reply, etc. Imagine what would happen if the request was stuck in a buffer.... You'd be waiting for the reply forever! 请求,回复,请求,回复等。想象一下如果请求被卡在缓冲区中会发生什么......你将永远等待回复!

From IO::Handle : 来自IO :: Handle

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

No magic. 没有魔法。

from : 来自

$| $ |

If set to nonzero, forces a flush right away and after every write or print on the currently selected output channel. 如果设置为非零,则在当前所选输出通道上的每次写入或打印后立即强制刷新。 Default is 0 (regardless of whether the channel is really buffered by the system or not; $| tells you only whether you've asked Perl explicitly to flush after each write). 默认值为0(无论系统是否真正缓冲了通道; $|仅告诉您是否在每次写入后都明确要求Perl进行刷新)。 STDOUT will typically be line buffered if output is to the terminal and block buffered otherwise. 如果输出到终端,则STDOUT通常是线路缓冲的,否则阻塞。 Setting this variable is useful primarily when you are outputting to a pipe or socket, such as when you are running a Perl program under rsh and want to see the output as it's happening. 设置此变量主要在输出到管道或套接字时很有用,例如在rsh下运行Perl程序并希望在输出时看到输出。 This has no effect on input buffering. 这对输入缓冲没有影响。 See getc for that. 请参阅getc See select on how to select the output channel. 请参阅选择如何选择输出通道。 See also IO::Handle . 另请参阅IO :: Handle

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM