Perl Net::SSLeay 检查套接字是否可读
Perl Net::SSLeay check if socket is available to read
我正在使用一个名为 Net::APNS::Persistent 的 perl 模块。它帮助我打开与苹果的 apns server 的持久连接并通过 APNS 发送推送通知。此模块使用 Net::SSLeay 与 APNS 服务器进行 ssl 通信。
现在,我想定期从我的套接字读取以检查 APNS 是否发回任何响应。 Net::APNS::Persistent 已经有一个名为 _read() 的函数,如下所示:
sub _read {
my $self = shift;
my ($socket, $ctx, $ssl) = @{$self->_connection};
my $data = Net::SSLeay::ssl_read_all( $ssl );
die_if_ssl_error("error reading from ssl connection: $!");
return $data;
}
但是,此功能仅在 APNS 断开连接并且我在尝试写入时出错时才有效。在其他时候,我的脚本卡在了
my $data = Net::SSLeay::ssl_read_all( $ssl );
我查看了 Net::SSLeay 文档,发现它有一个名为 peek 的方法
Copies $max bytes from the specified $ssl into the returned value. In contrast to the Net::SSLeay::read() function, the data in the SSL buffer is unmodified after the SSL_peek() operation.
虽然它可能有用,但我在 Net::APNS::Persistent 模块中添加了另一个函数:
sub ssl_peek {
my $self = shift;
my ($socket, $ctx, $ssl) = @{$self->_connection};
print "Peeking \n";
my $data = Net::SSLeay::peek( $ssl, $pending );
print "Done peeking \n";
return $data;
}
不幸的是,这也给了我同样的问题。它只打印 Peeking 而永远不会到达打印 Done peeking 的行。使用 Net::SSLeay::read 时遇到同样的问题。有没有办法检查套接字是否可以读取或设置读取超时,以便我的脚本在尝试从套接字读取时不会卡住?
检查是否可以读取底层套接字使用select,即
IO::Select->new(fileno($socket))->can_read(timeout);
超时可以是 0
只检查而不等待,可以是秒数或者可以是 undef
永远等待。但在执行 select 之前,请检查 SSL 缓冲区中的数据是否仍然可用:
if (Net::SSLeay::pending($ssl)) { ... use SSL_peek or SSL_read ... }
除此之外,您使用的模块看起来确实没有尝试验证服务器证书:(
APNS documentation 表示如下:
If you send a notification that is accepted by APNs, nothing is returned.
If you send a notification that is malformed or otherwise unintelligible, APNs returns an error-response packet and closes the connection. Any notifications that you sent after the malformed notification using the same connection are discarded, and must be resent
只要您的通知被接受,就不会有任何数据要读取,因此对套接字的读取操作将被阻止。唯一可用的数据是出现错误时,然后连接立即关闭。这应该可以解释您观察到的行为。
我正在使用一个名为 Net::APNS::Persistent 的 perl 模块。它帮助我打开与苹果的 apns server 的持久连接并通过 APNS 发送推送通知。此模块使用 Net::SSLeay 与 APNS 服务器进行 ssl 通信。
现在,我想定期从我的套接字读取以检查 APNS 是否发回任何响应。 Net::APNS::Persistent 已经有一个名为 _read() 的函数,如下所示:
sub _read {
my $self = shift;
my ($socket, $ctx, $ssl) = @{$self->_connection};
my $data = Net::SSLeay::ssl_read_all( $ssl );
die_if_ssl_error("error reading from ssl connection: $!");
return $data;
}
但是,此功能仅在 APNS 断开连接并且我在尝试写入时出错时才有效。在其他时候,我的脚本卡在了
my $data = Net::SSLeay::ssl_read_all( $ssl );
我查看了 Net::SSLeay 文档,发现它有一个名为 peek 的方法
Copies $max bytes from the specified $ssl into the returned value. In contrast to the Net::SSLeay::read() function, the data in the SSL buffer is unmodified after the SSL_peek() operation.
虽然它可能有用,但我在 Net::APNS::Persistent 模块中添加了另一个函数:
sub ssl_peek {
my $self = shift;
my ($socket, $ctx, $ssl) = @{$self->_connection};
print "Peeking \n";
my $data = Net::SSLeay::peek( $ssl, $pending );
print "Done peeking \n";
return $data;
}
不幸的是,这也给了我同样的问题。它只打印 Peeking 而永远不会到达打印 Done peeking 的行。使用 Net::SSLeay::read 时遇到同样的问题。有没有办法检查套接字是否可以读取或设置读取超时,以便我的脚本在尝试从套接字读取时不会卡住?
检查是否可以读取底层套接字使用select,即
IO::Select->new(fileno($socket))->can_read(timeout);
超时可以是 0
只检查而不等待,可以是秒数或者可以是 undef
永远等待。但在执行 select 之前,请检查 SSL 缓冲区中的数据是否仍然可用:
if (Net::SSLeay::pending($ssl)) { ... use SSL_peek or SSL_read ... }
除此之外,您使用的模块看起来确实没有尝试验证服务器证书:(
APNS documentation 表示如下:
If you send a notification that is accepted by APNs, nothing is returned.
If you send a notification that is malformed or otherwise unintelligible, APNs returns an error-response packet and closes the connection. Any notifications that you sent after the malformed notification using the same connection are discarded, and must be resent
只要您的通知被接受,就不会有任何数据要读取,因此对套接字的读取操作将被阻止。唯一可用的数据是出现错误时,然后连接立即关闭。这应该可以解释您观察到的行为。