Perl中的非致命性处理错误
在上一篇文章中,建议我使用该模块导出和发送RSA密钥。但是,我发现该模块似乎无法非致命地处理错误,因此,只要发送一个格式错误的字符串(即不是RSA密钥),服务器程序就会在尝试使用它创建新对象时崩溃,并显示以下消息: server.pl第46行的密钥格式无法识别 第46行包含代码Perl中的非致命性处理错误,perl,encryption,error-handling,cryptography,Perl,Encryption,Error Handling,Cryptography,在上一篇文章中,建议我使用该模块导出和发送RSA密钥。但是,我发现该模块似乎无法非致命地处理错误,因此,只要发送一个格式错误的字符串(即不是RSA密钥),服务器程序就会在尝试使用它创建新对象时崩溃,并显示以下消息: server.pl第46行的密钥格式无法识别 第46行包含代码 $clients{$cur_client}->{pub_key} = Crypt::OpenSSL::RSA->new_public_key($message) or do {
$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
我该如何解决这个问题
编辑:您需要使用的块形式来防止程序在引发异常时死机。不幸的是,
eval
的简单使用充满了尴尬的角落案例,最好使用为您处理这些案例的模块
为了达到问题中代码的目的,您可以编写如下内容。显然,您必须为变量提供有用的数据
重要的是要注意try
和catch
是子例程。这意味着您在catch
之后需要一个分号,并且您不能在catch
中使用next
,因为您不能在子例程中使用分号。您必须保留某种状态集,以便后续代码可以在那里执行任何必要的操作,在这种情况下,我只需检查$clients{$cur_client}
是否仍然存在,如果出现问题,它将被catch
例程删除
还需要说明的是,catch
例程中的$\ucode>中提供了die
字符串,因此您可以检查失败的原因。在这种情况下,catch
只希望处理无法识别的密钥格式
错误,因此代码检查这确实是失败的原因。如果没有,则它会发出另一个die$\uu
,以反映发生了未处理的错误
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";
}
您需要使用的块形式来防止程序在引发异常时死机。不幸的是,eval
的简单使用充满了尴尬的角落案例,最好使用为您处理这些案例的模块
为了达到问题中代码的目的,您可以编写如下内容。显然,您必须为变量提供有用的数据
重要的是要注意try
和catch
是子例程。这意味着您在catch
之后需要一个分号,并且您不能在catch
中使用next
,因为您不能在子例程中使用分号。您必须保留某种状态集,以便后续代码可以在那里执行任何必要的操作,在这种情况下,我只需检查$clients{$cur_client}
是否仍然存在,如果出现问题,它将被catch
例程删除
还需要说明的是,catch
例程中的$\ucode>中提供了die
字符串,因此您可以检查失败的原因。在这种情况下,catch
只希望处理无法识别的密钥格式
错误,因此代码检查这确实是失败的原因。如果没有,则它会发出另一个die$\uu
,以反映发生了未处理的错误
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";
}
我知道这个问题已经得到了回答,但我想我应该添加它,这样人们就知道,在Perl中捕获错误不需要模块,它已经内置了。下面是一些演示Perls内置异常处理的代码
#!/usr/bin/perl
use strict;
use warnings;
my $a = 100;
my $res = 0;
eval {
$res = $a/0;
};
if($@) {
print("I just caught a divide by zero here... $@\n");
}
这是另一个例子
eval {
die "please die\n";;
};
if($@) {
print("No, you cannot die just yet... $@\n");
}
我已经使用这个习惯用法很多年了,它的效果非常好。我知道这个问题已经得到了回答,但我想我应该添加它,这样人们就知道,在Perl中捕获错误不需要模块,它已经内置了。下面是一些演示Perls内置异常处理的代码
#!/usr/bin/perl
use strict;
use warnings;
my $a = 100;
my $res = 0;
eval {
$res = $a/0;
};
if($@) {
print("I just caught a divide by zero here... $@\n");
}
这是另一个例子
eval {
die "please die\n";;
};
if($@) {
print("No, you cannot die just yet... $@\n");
}
我已经使用这个成语很多年了,它很有魅力。公认的答案首先提到了eval
,然后建议Try::Tiny
更可取,因为eval
有很多陷阱,你可能会落入其中,Try::Tiny
可以避免它们。例如,如果$@
具有非真值,则错误处理代码将无法检测到发生错误。公认的答案首先提到了eval
,然后建议首选Try::Tiny
,因为eval
有许多陷阱,您可能会落入其中,而Try::Tiny
可以避免这些陷阱。例如,如果$@
具有非真值,则错误处理代码将无法检测到发生错误。