2010-03-03 75 views
5

我有一个ruby脚本,打开与Apple推送服务器的连接并发送所有待处理的通知。我看不到任何理由,但是当苹果断开我的脚本时,我得到了管道错误。我已经写了我的脚本来适应这种情况,但我宁愿找出它发生的原因,以便我可以首先避免它。什么会导致与APNS的连接间歇性断开连接?

它不会在特定通知中始终断开连接。它不会以某个字节传输大小断开连接。一切似乎都是零星的。您可以通过单个连接发送的数据传输或有效负载数量是否存在某些限制?看到人们一直在打开一个连接的解决方案,我会认为这不是问题。在3次通知后,我看到连接数下降了,并且在14次通知后我看到它下降了。我从来没有见过它通过14.

有其他人遇到过这种类型的问题?这怎么处理?

回答

11

问题是由于向APNS服务器发送无效的设备令牌而导致的。在这个特定的情况下,这是一个发展的象征。当一个无效的设备令牌发送给APNS时,它将断开套接字。这可能会引起一些令人头疼的问题,并且Apple已将其视为将来更新中要解决的问题。

+0

你从哪里看到他们要解决它?你做了什么来解决这个问题?关闭并重新打开插座? – Sam 2013-05-31 05:42:49

2

我有同样的问题了一下,做了两件事情来解决它:

  1. 把一些自动重新连接逻辑的地方:我尽量保持我的,只要可能的,但苹果的连接将断开你时不时地。准备好处理这个问题。
  2. 移动到增强的界面:使用简单的界面(这就是APNS创业板和其他许多人使用的)错误将在没有任何反馈的情况下触发断开连接。如果切换到enhanced format,则每次发生事件时都会收到一个整数。不好的令牌会导致返回8,我用它从我的数据库中删除设备。

这里是我当前的连接代码,使用EventMachine的:

module Apns 

    module SocketHandler 
    def initialize(wrapper) 
     @wrapper = wrapper 
    end 

    def post_init 
     start_tls(:cert_chain_file => @wrapper.pem_path, 
       :private_key_file => @wrapper.rsa_path, 
       :verify_peer => false) 
    end 

    def receive_data(data) 
     @wrapper.read_data!(data) 
    end 

    def unbind 
     @wrapper.connection_closed! 
    end 

    def write(data) 
     begin 
     send_data(data) 
     rescue => exc 
     @wrapper.connection_error!(exc) 
     end 
    end 

    def close! 
     close_connection 
    end 
    end 

    class Connection 
    attr_reader :pem_path, :rsa_path 

    def initialize(host, port, credentials_path, monitoring, read_data_handler) 
     setup_credentials(credentials_path) 
     @monitoring = monitoring 
     @host = host 
     @port = port 
     @read_data_handler = read_data_handler 
     open_connection! 
    end 

    def write(data) 
     @connection.write(data) 
    end 

    def open? 
     @status == :open 
    end 

    def connection_closed! 
     @status = :closed 
    end 

    def connection_error!(exception) 
     @monitoring.inform_exception!(exception, self) 
     @status = :error 
    end 

    def close! 
     @connection.close! 
    end 

    def read_data!(data) 
     @read_data_handler.call(data) 
    end 

    private 
    def setup_credentials(credentials_path) 
     @pem_path = "#{credentials_path}.pem" 
     @rsa_path = "#{credentials_path}.rsa" 
     raise ArgumentError.new("#{credentials_path}.pem and #{credentials_path}.rsa must exist!") unless (File.exists?(@pem_path) and File.exists?(@rsa_path)) 
    end 

    def open_connection! 
     @connection = EventMachine.connect(@host, @port, SocketHandler, self) 
     @status = :open 
    end 
    end 
end 

末 结束

它分离写入和读取的连接,使用在通知相关通知我送ID字段与我收到的反馈。