我有一个向远程SSL服务器发送消息的方法。该类嵌入在可以从命令行调用的程序中,或者程序可以作为守护程序启动,并可以根据请求调用类方法。我使用Net::Server::Fork
启动守护进程:
package myserver;
use 5.10.1;
use strict;
use warnings;
use parent 'Net::Server::Fork';
myserver->run(
'port' => $main::config{'backend.ssl.host'} . '/ssl',
'ipv' => '*',
'log_level' => $main::config{'backend.loglevel'},
'log_file' => $main::config{'backend.logfile'},
'pid_file' => $main::config{'backend.pidfile'},
'user' => $main::config{'backend.user'},
'group' => $main::config{'backend.group'},
'max_servers' => $main::config{'backend.maxconnections'},
'background' => !$main::config{'backend.foreground'},
'leave_children_open_on_hup' => 1,
'allow' => $main::config{'ip'},
'reverse_lookups' => 1,
'SSL_key_file' => $main::config{'backend.ssl.key'},
'SSL_cert_file' => $main::config{'backend.ssl.crt'},
'SSL_ca_file' => $main::config{'backend.ssl.bundle'},
);
sub process_request {
# call connect and sendframe if requested
};
外部通信类与IO::Socket::SSL
连接,并通过将数据包长度作为4字节标头添加前发送数据,然后按原样发送消息:
package communicator;
use 5.10.1;
use strict;
use warnings;
use IO::Socket::SSL;
sub connect {
my $self = shift @_;
my $server = shift @_;
my @field = split /\:/, $server;
my $socket;
$socket = IO::Socket::SSL->new(
'PeerAddr' => $field[0],
'PeerPort' => $field[1],
'Blocking' => 1,
);
if ( $socket ) {
binmode $socket;
}
else {
# error handling
};
$self->{'SOCK'} = $socket;
};
sub sendframe {
my $self = shift @_;
my $msg = shift @_;
if ($self->{'SOCK'}) {
my $length = pack("N", bytes($msg));
($self->{'SOCK'})->print($length);
($self->{'SOCK'})->print($msg);
};
};
从命令行调用时可以正常工作,但在作为Net::Server
进程运行时失败。我已经尝试记录发送到远程服务器的内容,但两种方法的日志文件都是相同的。
我编写了一个最小的SSL服务器来捕获内容,并发现当Net::Server
运行时,套接字上的每个打印都会为正在发送的内容添加换行符。所以服务器收到
[packet length in binary]Line 1
Line 2
--- [Received announced length + 4 bytes]
直接通话
[packet length in binary]
Line 1
Line 2
--- [Received announced length + 6 bytes]
在Net::Server
正在运行的通话中。当然这会破坏与外部服务器的通信。
我怀疑Net::Server
在IO::Socket::SSL
中设置了一个全局配置变量,混淆了对sendframe
的后续调用,但我无法确定它可能是哪个变量。
请注意我正在使用外部库连接到我自己的communicator
类之外的其他服务器。该库也使用IO::Socket::SSL
并遇到同样的问题,因此我更倾向于使用IO::Socket::SSL
以外的其他内容修复$socket->print
。
我可以修补外部库,但每次有更新时都可能必须这样做。
我的系统是Debian 7,包含Perl 5.14,IO :: Socket :: SSL 2.020和Net :: Server 2.006
答案 0 :(得分:3)
print
在其他文件句柄上的行为类似print
,因为它尊重$\
的设置。来自perldoc perlvar
:
$\ The output record separator for the print operator.
If defined, this value is printed after the last of print's
arguments. Default is "undef".
由于默认情况下此变量为undef,因此只有有人明确设置此变量时才会发生变化。我看不到Net :: Server在任何地方设置这个变量。也许它在您自己的代码或您使用的其他模块中?如果您不会影响其他代码,您可以对变量进行本地化,即
if ($self->{'SOCK'}) {
local $\ = undef; ### make sure to disable side effects
my $length = pack("N", bytes($msg));
($self->{'SOCK'})->print($length);
($self->{'SOCK'})->print($msg);
};