Perl Net :: SSLeay检查socket是否可以读取

时间:2015-10-07 20:51:57

标签: perl ssl apple-push-notifications

我正在使用一个名为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 doc并发现它有一个名为peek的方法

  

将指定$ ssl中的$ max个字节复制到返回值中。与Net :: SSLeay :: read()函数相反,在SSL_peek()操作之后,SSL缓冲区中的数据不会被修改。

我虽然它可能有用,所以我在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偷看的行。使用Net :: SSLeay :: read有同样的问题。有没有办法检查套接字是否可以读取或设置读取超时,以便我的脚本在尝试从套接字读取时不会卡住?

2 个答案:

答案 0 :(得分:1)

要检查底层套接字是否可以读取,请使用select,即

 IO::Select->new(fileno($socket))->can_read(timeout);

超时可以0来检查而不是等待,可以是几秒钟,也可以undef永远等待。但在进行选择之前,请检查SSL缓冲区中是否仍有数据:

 if (Net::SSLeay::pending($ssl)) { ... use SSL_peek or SSL_read ... }

除此之外,您使用的模块看起来确实甚至没有尝试验证服务器证书:(

答案 1 :(得分:1)

APNS documentation说明如下:

  

如果您发送APN接受的通知,则不会返回任何内容。

     

如果发送格式错误或无法识别的通知,APN将返回错误响应数据包并关闭连接。在使用相同连接的格式错误通知后发送的任何通知都将被丢弃,并且必须重新发送

只要您的通知被接受,就不会有任何数据要读取,因此套接字上的读取操作将被阻止。有数据可用的唯一时间是出现错误,然后立即关闭连接。这应该可以解释你正在观察的行为。