我试图用 perl 尽快写入 unix 套接字文件,但在完整消息缓冲区上失败。我尝试了自动刷新和手动刷新但没有成功。
use IO::Select;
use IO::Socket::UNIX;
my $sock = IO::Socket::UNIX->new(
Type => IO::Socket::SOCK_DGRAM,
Peer => "/dev/log",
) or die "$!\n";
$sock->autoflush(1);
my $sel = IO::Select->new($sock);
my $cnt = 0;
while(<>){
$sel->can_write or die "1 line $cnt: $!\n";
$sock->say($_) or die "2 line $cnt: $!\n";
$sock->flush or die "3 line $cnt: $!\n";
$cnt++;
}
$sock->close();
输出总是2 line 64: No buffer space available
更新:我不固定使用 Perl。也许有一些更好的方法可以发送到 IBM AIX 上的套接字。
答案1
正如您所观察到的,尝试更快地向已满的网络堆栈发送更多数据是行不通的。至少,这比尝试将更多数据倒入已经满的浴室下水道中要简单一些。无论如何,这里的发送者必须等待,直到条件清除,或者网络堆栈的缓冲区可能会增加,这将导致数据在其他地方(可以这么说,在内核的化粪池中)汇集,直到它可以被处理。另外,数据报并不真正知道有要刷新的流,并且$.
Perl 变量已经完成了您的工作$cnt
,所以
#!/usr/bin/env perl
use strict;
use warnings;
use Errno ':POSIX';
use IO::Socket::UNIX;
use Time::HiRes 'usleep';
my $peer = shift || die "Usage: $0 /dev/log\n";
my $sock = IO::Socket::UNIX->new(
Peer => $peer,
Type => IO::Socket::SOCK_DGRAM,
) or die "socket failed '$peer': $!\n";
LINE: while (<>) {
$sock->print($_) and next;
if ($!{ENOBUFS}) {
while (1) {
# exponential backoff might be more typical and less rude
# here, or the code could try to be smart about how long to
# wait for, but that takes more code and more memory and
# more effort on the part of the programmer
usleep(128);
$sock->print($_) and last;
# PORTABILITY and there may be a bunch of different error
# messages from trying to go too fast here with a full
# buffer, check for them ...
unless ($!{EMSGSIZE} or $!{ENOBUFS} or $!{ETIMEDOUT}) {
my $errno = 0 + $!;
die "print failed line $.: $! ($errno)";
}
}
} else {
my $errno = 0 + $!;
die "print failed line $.: $! ($errno)";
}
}