2016-03-05 36 views
0

在我以前的question中,建议使用模块Crypt::OpenSSL::RSA来导出和发送RSA密钥。但是,我发现这个模块似乎没有非致命的错误处理方式,并且通过简单地发送格式错误的字符串(即不是RSA密钥),服务器程序在尝试创建新对象时会崩溃它与消息:Perl中的非致命处理错误

未知键格式的server.pl线46

46行包含的代码

$clients{$cur_client}->{pub_key} = Crypt::OpenSSL::RSA->new_public_key($message) or do { 
      server_log "Bad key exchange, dropping user $address:$port..."; 
      delete $clients{$cur_client}; 
      next; 
     }; # Key exchange 

我该如何解决这个问题?

编辑:Here is a link to the full code on Github

回答

6

您需要使用的eval块形式,以防止程序时,将引发异常死亡。不幸的是,eval的裸露使用充满了令人尴尬的角落案例,最好使用Try::Tiny模块来处理这些模块。

为了在您的问题中达到您的代码目的,您可以编写类似这样的内容。显然,你将不得不为变量

重要的是要注意trycatch子程序是非常重要的供应有用的数据。这意味着在catch之后你需要一个分号,并且你不能在catch之内设置next,因为你不能在子程序中做到这一点。您必须保留某种状态设置,以便后续代码可以执行必要的任何操作,在这种情况下,我只需检查$clients{$cur_client}是否仍然存在 - 如果出现问题,它将被catch例程删除

另外值得说明的是,die字符串可在catch例程中的$_中使用,因此您可以检查失败原因。在这种情况下,catch期望仅处理unrecognized key format错误,所以代码检查确实是失败的原因。如果没有,那么它会发出另一种die $_,以反映已发生未处理的错误

use strict; 
use warnings 'all'; 

use Crypt::OpenSSL::RSA; 
use Try::Tiny; 

my %clients = (aa => {}); 
my $message = 'xxx'; 
my ($address, $port) = qw/ 127.0.0.1 80 /; 

for my $cur_client (keys %clients) { 

    try { 
     $clients{$cur_client}{pub_key} = Crypt::OpenSSL::RSA->new_public_key($message); 
    } 
    catch { 
     if (/unrecognized key format/) { 
      server_log("Bad key exchange, dropping user $address:$port..."); 
      delete $clients{$cur_client}; 
     } 
     else { 
      die $!; 
     } 
    }; 

    next unless exists $clients{$cur_client}; 

    # More handling of $cur_client in the case that 
    # the call to new_public_key succeeds 
} 

sub server_log { 
    print "Logging: $_[0]\n"; 
} 
0

我知道这已经回答了,但我想我会添加它让人们都知道,你并不需要一个模块在Perl中捕获错误,它已经内置。下面是一些代码演示皮尔斯内置的异常处理...

#!/usr/bin/perl 
use strict; 
use warnings; 
my $a = 100; 
my $res = 0; 
eval { 
    $res = $a/0; 
}; 
if([email protected]) { 
    print("I just caught a divide by zero here... [email protected]\n"); 
} 

继承人另一个例子......

eval { 
    die "please die\n";; 
}; 
if([email protected]) { 
    print("No, you cannot die just yet... [email protected]\n"); 
} 

我用这个成语多年,它像一个魅力的工作。

+2

接受的答案首先提到'eval',之前建议'Try :: Tiny'是可取的,因为'eval'有许多陷阱可以陷入,'Try :: Tiny'避免它们。例如,如果'$ @'具有非真值,那么您的错误处理代码将无法检测到发生了错误。 https://metacpan.org/pod/Try::Tiny#might-not-be-a-true-value –