尽可能快地写入unix套接字文件

尽可能快地写入unix套接字文件

我试图用 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)";
    }
}

相关内容