3

解決

私が受け入れた回答で@limulusによって報告されたように、これはNet::HTTPSバージョン6.00のバグでした。常に新しい.0リリースに注意してください。そのモジュールのバグのあるバージョンと修正されたバージョンの関連する違いは次のとおりです。

D:\Opt\Perl512.32 :: diff lib\Net\HTTPS.pm site\lib\Net\HTTPS.pm
6c6
< $VERSION = "6.00";
---
> $VERSION = "6.02";
75,78c75,80
< # The underlying SSLeay classes fails to work if the socket is
< # placed in non-blocking mode.  This override of the blocking
< # method makes sure it stays the way it was created.
< sub blocking { }  # noop
---
> if ($SSL_SOCKET_CLASS eq "Net::SSL") {
>     # The underlying SSLeay classes fails to work if the socket is
>     # placed in non-blocking mode.  This override of the blocking
>     # method makes sure it stays the way it was created.
>     *blocking = sub { };
> }

元の質問

関連性:接続エンドポイントの信頼性が低いため、HTTPSクライアントブロックが無期限に表示されるのは面倒です。

この実験は、自宅で簡単に設定して再生できます。必要なのは、着信クライアントをトラップするためのtarpitとPerlスクリプトの2つだけです。ターピットは、以下を使用して設定できますnetcat

nc -k -l localhost 9999 # on Linux, for multiple requests
nc -l -p 9999 localhost # on Cygwin, for one request only

次に、スクリプトで次のターピットを指定します。

use strict;
use LWP::UserAgent;
use HTTP::Request::Common;

print 'LWP::UserAgent::VERSION  ', $LWP::UserAgent::VERSION, "\n";
print 'IO::Socket::SSL::VERSION ', $IO::Socket::SSL::VERSION, "\n";

my $ua = LWP::UserAgent->new( timeout => 5, keep_alive => 1 );
$ua->ssl_opts( timeout => 5, Timeout => 5 ); # Yes - see note below!
my $rsp = $ua->request( GET 'https://localhost:9999' );
if ( $rsp->is_success ) {
  print $rsp->as_string;
} else {
  die $rsp->status_line;
}

これは何をするつもりですか?さて、NetCatによって開かれたポートに接続してから...ハングします。無期限に。少なくとも開発者の時間に関しては。10分か2時間後にタイムアウトするかもしれませんが、私はチェックしていません。指定されたタイムアウトは、LinuxでもWindowsでも有効になりません(Win32、Cygwinをチェックしていません)。

使用したバージョン:

LWP::UserAgent::VERSION  6.02
IO::Socket::SSL::VERSION 1.44
# on Linux

LWP::UserAgent::VERSION  6.02
IO::Socket::SSL::VERSION 1.44
# on Win32

次に、timeoutTimeoutパラメータについて説明します。前者はLWP::UAのパラメーターの名前であり、後者はIO :: Socket :: SSLの名前であり、 LWP :: Protocol::httpsを介して使用されます。(ちなみに、なぜmetacpan HTTPSなのですか?まあ、少なくともそれはターピットではありません。)私はどういうわけかこれらのパラメーターを渡してもらいたいと思っています:)

ご存知のとおり、keep_aliveタイムアウトが機能しないこととは何の関係もありません。経験的に検証しました。:)

とにかく、深く掘り下げる前に、ここで何が起こっているのか、HTTPSでタイムアウトを機能させる方法を誰かが知っていますか?私がこれに遭遇した最初の人だとは信じがたい。

4

3 に答える 3

4

これは、Net::HTTPSモジュールがnoopでのblockingメソッドをオーバーライドした結果です。最新のパッケージIO::Socketにアップグレードすると、これが修正されるはずです。Net::HTTP

于 2012-04-20T07:31:11.930 に答える
3

timeout(およびTimeout)オプションは、接続(接続中に待機する秒数)にのみ適用されます。LWP::UserAgentこれらは、トランザクション全体にタイムアウトを設定するためのものではありません。

ハンドラーでPerlを使用alarmして、トランザクション全体をタイムアウトする必要があります。または$SIG{ALRM}を参照してください。perldoc -f alarmperlipc

local $SIG{ALRM} = sub { die "SSL timeout\n" };
my $ua = LWP::UserAgent->new( timeout => 5, keep_alive => 1 );
$ua->ssl_opts( timeout => 5, Timeout => 5 );

eval {
    alarm(10);
    my $rsp = $ua->request( GET 'https://localhost:9999' );
    if ( $rsp->is_success ) {
      print $rsp->as_string;
    } else {
      die $rsp->status_line;
    }
 };
 alarm(0);
 if ($@) {
     if ($@ =~ /SSL timeout/) {
         warn "request timed out";
     } else {
         die "error in request: $@";
     }
 }

(Linuxでテスト済み。Windows/ Cygwinではアラームが少し厄介になる可能性があります

于 2012-02-22T19:10:21.993 に答える
0

私はPerlMonksでこの質問をし、次のような効果に対する回答を受け取りました。

基盤となるIO::Socket :: INETはWin32で非ブロッキングソケットをサポートしていないため、Win32では非ブロッキングIO :: Socket :: SSLはサポートされていません。つまり、タイムアウトは機能しません(非ブロッキングに基づく)。http://www.perlmonks.org/?node_id=378675も参照してください。

http://cpansearch.perl.org/src/SULLR/IO-Socket-SSL-1.60/README.Win32

指摘されたPerlMonksの投稿は2004年のものです。情報がまだ適用されているかどうかはわかりません。結局のところ、タイムアウトSSL経由ではなく、Windowsで機能することを確認しました。

于 2012-03-26T09:04:48.773 に答える