2016-03-05 61 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 –