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)";
}
}