2010-03-03 78 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字段與我收到的反饋。