LWPとそれに関連するライブラリが私たちのホスティングの一部で利用できないので、LWP::UserAgent
のget
メソッドをエミュレートするために、比較的単純なライブラリ関数を記述しようとしています。私が頼りにできるのはPerlの中核機能であり、制限されているものもありますが、ソケット、フォーク、シグナルなどにアクセスできるようです。制限付き環境のTCPソケットでノンブロッキングI/Oを実行する
これまでデータを送受信できる単純なクライアントとサーバー(サーバーはテスト専用)を作成していました。問題は、私はLWPのように全部でget
の操作でタイムアウトを設定したいのですが、私の最初の試みは無駄でした。以下では動作しないと私はそれが動作することができます信じていませんが、私はちょうどそれが固定されることができる場合にはそれを投稿します。
sub grab {
my($addr, $port, $timeout) = @_;
my $it;
eval {
local $SIG{ALRM} = sub {
die "alarm\n";
};
alarm $timeout if $timeout;
my $iaddr = inet_aton($addr)
or die "client no host: $!";
my $paddr = sockaddr_in($port, $iaddr)
or die "client sockaddr_in: $!";
my $proto = getprotobyname("tcp");
socket(Client, PF_INET, SOCK_STREAM, $proto)
or die "Client socket: $!";
local $SIG{ALRM} = sub {
close(Client);
die "alarm\n";
};
connect(Client, $paddr)
or die "Client connect: $!";
while(my $line = <Client>) {
$it .= $line;
}
print alarm(0), " seconds left \n";
close(Client) or die "Client close: $!";
};
if([email protected]) {
die unless [email protected] eq "alarm\n";
}
return $it;
}
アラーム信号は、接続の同類によって無視され得るように見える、読み、おそらく他のもののいくつか。私は間違ってツリーを吠えたように私は感じたので - - 私はこれが仕事に失敗した後LWPのソースコードを読むに頼っおよびその他の宝石の中で、次のことを見つけ、strawberry/perl/vendor/lib/LWP/Protocol/http.pm
中:
sub sysread {
my $self = shift;
if (my $timeout = ${*$self}{io_socket_timeout}) {
die "read timeout" unless $self->can_read($timeout);
}
else {
# since we have made the socket non-blocking we
# use select to wait for some data to arrive
$self->can_read(undef) || die "Assert";
}
sysread($self, $_[0], $_[1], $_[2] || 0);
}
sub can_read {
my($self, $timeout) = @_;
my $fbits = '';
vec($fbits, fileno($self), 1) = 1;
SELECT:
{
my $before;
$before = time if $timeout;
my $nfound = select($fbits, undef, undef, $timeout);
if ($nfound < 0) {
if ($!{EINTR} || $!{EAGAIN}) {
# don't really think EAGAIN can happen here
if ($timeout) {
$timeout -= time - $before;
$timeout = 0 if $timeout < 0;
}
redo SELECT;
}
die "select failed: $!";
}
return $nfound > 0;
}
}
だから、それはそれのように見えますselectを使用して他のサブルーチンの制限のいくつかを処理しますか?また、シグナルをフォークしたり、使用したりすることはありません。厳密に言えば、時折ブロックされますが、ブロックされないようにしていますか?私はこのコードの要点をコピーして、私の特定のニーズに合わせて簡略化したバージョンを作成する必要があるように感じますが、私は地雷に遭遇するのを慎重に始めています。また、私はWindows上で開発していますが、Linux/nix *や今後のWindowsにも展開しています。
を選択-f、それはあなたが実際に言っているものであれば、選択して、私は右のコースにしています私に言ってくれてありがとう私。私の質問の前提は愚かですが、私がコーディングしている環境を管理していません。LWPとその依存関係をバンドルすることはオプションではないと考えることができます。私が簡素化と言うとき、私はLWPとそのすべての依存関係(例えばHTTPモジュール)を完全に再実装するつもりはないということです。絶対的な基本よりも多くのHTTPを理解する必要はないので、私のライブラリはLWPよりも大幅に小さくなり、必要に応じて別のスクリプトにコピーすることができます。 – Richie
実際には、選択は行く方法です。しかし、 "私はmor HTTPを理解する必要はありません..."というメッセージは、いつかあなたを噛んでくれるでしょう。 @少なくとも、リモートでも便利になるGETクライアントは、3xxリダイレクトを処理する必要があります。これは初心者向けです。 –
私がアクセスするサーバは、私にリダイレクトまたはプロキシを投げるべきではありません。それは一般的にOK 200でなければなりません。スクリプトが失敗して放棄されます(HTTPプロキシはほとんどの場合透過的ではありませんか?それが当てはまらない場合は、私はいつも密かに、深く考えて、PerlでHTTPプロトコルの良い部分を再実装したかったと思います。 – Richie