IO::Socket:SSL 在套接字上打印时有时会添加换行符
IO::Socket:SSL sometimes adds newline when printing on socket
我有一种方法可以将消息发送到远程 SSL 服务器。 class 嵌入到可以从命令行调用的程序中,或者该程序可以作为守护进程启动,并可以根据请求调用 class 方法。我使用 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
};
外部通信class与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
class,我还使用外部库连接到其他服务器。该库也使用 IO::Socket::SSL
并遇到同样的问题,所以我宁愿修复 IO::Socket::SSL
而不是使用 $socket->print
.
以外的东西
我可以修补外部库,但每次有更新时可能都必须这样做。
我的系统是带有 Perl 5.14、IO::Socket::SSL 2.020 和 Net::Server 2.006
的 Debian 7
print
在 IO::Socket::SSL 句柄上的行为类似于 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);
};
我有一种方法可以将消息发送到远程 SSL 服务器。 class 嵌入到可以从命令行调用的程序中,或者该程序可以作为守护进程启动,并可以根据请求调用 class 方法。我使用 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
};
外部通信class与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
class,我还使用外部库连接到其他服务器。该库也使用 IO::Socket::SSL
并遇到同样的问题,所以我宁愿修复 IO::Socket::SSL
而不是使用 $socket->print
.
我可以修补外部库,但每次有更新时可能都必须这样做。
我的系统是带有 Perl 5.14、IO::Socket::SSL 2.020 和 Net::Server 2.006
的 Debian 7print
在 IO::Socket::SSL 句柄上的行为类似于 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);
};