가능한 한 빨리 유닉스 소켓 파일에 쓰기

가능한 한 빨리 유닉스 소켓 파일에 쓰기

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

관련 정보