【问题标题】:What does autoflush do in socket? why do we use it?autoflush 在套接字中做了什么?我们为什么用它?
【发布时间】:2013-02-08 01:23:09
【问题描述】:

我正在编写一些套接字代码,但无法弄清楚为什么套接字上使用了autoflush。是这样的

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

autoflush $sock 1;

还有一些地方

autoflush STDERR 1

autoflush STDOUT 1

用于一般文件。

它有什么作用?如果我不使用它会发生什么或将会发生什么?请举一些实际的例子,以便我理解而不是简单的定义。

【问题讨论】:

  • $sock->autoflush(1);STDOUT->autoflush(1);等的写法很奇怪

标签: perl sockets autoflush


【解决方案1】:

它绝对什么都不做......因为 IO::Socket::Unix 已经为你做了。

以块的形式发送数据的开销较小,因此文件库会累积数据以在缓冲区中打印,而不是立即发送到系统。只有当数据已经累积到 4KB 或 8KB(取决于版本)时,才是真正发送到系统的数据。这称为“缓冲”。

将句柄的 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::* 开启,因为大多数情况下套接字都需要它。套接字通常用于交互式通信。请求、回复、请求、回复等。想象一下,如果请求被卡在缓冲区中会发生什么......您将永远等待回复!

【讨论】:

  • 很高兴有一个例子来展示这个,想知道如何测试这个:)。
【解决方案2】:

来自IO::Handle

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

没有魔法。

from

$|

如果设置为非零,则在每次写入后立即强制刷新或 在当前选择的输出通道上打印。默认为 0 (无论通道是否真的被系统缓冲或 不是; $| 只告诉你是否明确要求 Perl 刷新 每次写入后)。如果输出是 STDOUT 通常会被行缓冲 到终端和块缓冲。设置这个变量是 主要在输出到管道或套接字时有用,例如 当您在 rsh 下运行 Perl 程序并想查看 发生时输出。这对输入缓冲没有影响。看 getc 为此。请参阅select 了解如何选择输出 渠道。另见IO::Handle

【讨论】:

  • 因为声誉问题不得不发布纯文本链接,对此感到抱歉。
【解决方案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 个字符
  • 非常简单的例子,你看到之后可能会提出一些其他的问题——其中很大一部分也是依赖于实现的。此外,缓冲可以发生在各个级别(发送方、接收方、应用程序等)

【讨论】:

  • 您仍然可以收到 tZZZyyXX 并启用自动刷新。它只控制数据如何发送到操作系统,但操作系统可能会将数据分组以发送到同一个包中。即使发送了多个数据包,接收方也会将数据包组合成一个流。
猜你喜欢
  • 2018-07-21
  • 2018-01-07
  • 2012-01-24
  • 2016-05-27
  • 2011-11-06
  • 2015-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多