我在本地机器上测试了推送通知,它运行得很好。然后,我用相同的证书(".pem"文件)将我的文件上传到真实的服务器,并确保端口2195和2196是打开的。
我测试过:
telnet gateway.sandbox.push.apple.com 2195
它正在工作。。。
root@server ~ # telnet gateway.sandbox.push.apple.com 2195
Trying 17.149.34.54...
Connected to gateway.sandbox.push.apple.com.
Escape character is '^]'.
但当我从php脚本进行测试时,它会返回:
警告:stream_socket_client()[function.stream socket-client]:无法连接到ssl://gateway.sandbox.push.apple.com:2195(连接超时)
警告:stream_socket_client()[function.stream socket-client]:无法连接到ssl://feedback.sandbox.push.apple.com:2196
有什么建议吗?
这是php代码:
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert',
"path/to/certificate");
$fp = stream_socket_client("ssl://gateway.push.apple.com:2195",
$error, $errorString, 100,
(STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT), $ctx);
此代码将正常工作:
$device = 'sdfsdfsfsdffsd';
$payload['aps'] = array('alert' => 'Hello I am testing the server code ....', 'badge' => 1, 'sound' => 'default');
$payload = json_encode($payload);
$options = array('ssl' => array(
'local_cert' =>'ck.pem',
'passphrase' => 'abc123'
));
$streamContext = stream_context_create();
stream_context_set_option($streamContext, $options);
$apns = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $error, $errorString, 60, STREAM_CLIENT_CONNECT, $streamContext);
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $device)) . chr(0) . chr(strlen($payload)) . $payload;
fwrite($apns, $apnsMessage);
fclose($apns);
只检查pem文件路径,并且端口处于打开状态。
我也遇到了同样的问题,无法连接到。。。(连接超时)'。我可以从家用机器连接,但不能从主机服务器连接。
在我的案例中,端口2195和2196并不是简单地从托管服务器打开的。我不得不联系技术支持来打开这些端口。Ping可能有效,因为它使用不同的端口号。因此,请联系您的托管服务公司,以确保这些端口是开放的。
祝你好运,
Kaz
在stream_socket_client
函数中,您不应该传递证书路径,而应该传递APNS url。
此方法打开连接并返回:
public function connect(){
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', '/your/cert/path');
$apns = stream_socket_client('use.apns.url.here', $error, $errorString, 9, STREAM_CLIENT_CONNECT, $streamContext);
if (!$apns){
$this->logger->error("Failed to connect to APNS: {$error} {$errorString}.");
}
return $apns;
}
一旦你建立了你的apns消息,你可以使用以下推送它
fwrite($apns, $apnsMessage);
您可以遵循本教程http://goo.gl/9Q0u如果您的目标是实现您自己的推送通知API。
还有现有的php库:
- http://code.google.com/p/apns-php/
- http://www.easyapns.com/
还有一个非常好的Java库(我目前使用它进行大规模推送):
- https://github.com/notnoop/java-apns
您必须设置防火墙以允许所有17.0.0.0/8块(它都属于Apple!)。检查此答案
根据苹果公司的说法:
APN服务器使用负载平衡,因此您的设备不会总是连接到同一个公共IP地址进行通知。最好允许访问分配给苹果的整个17.0.0.0/8地址块上的这些端口。
如果你正在使用CSF防火墙(像我一样),我建议在CSF.allow文件中添加这一行:
tcp|out|d=2195|d=17.0.0.0/8
使用它而不仅仅是"17.0.0.0/8"将只允许到苹果的外接连接,特别是到2195端口的外接。美国国家安全局不会喜欢它,但它更精确、更安全!)