2009-11-18 12 views
6

Ich habe ein seltsames Problem. Ich versuche, Apple Push-Benachrichtigungen mit Python arbeiten zu lassen. Ich kann einzelne Nachrichten verbinden und problemlos senden. Die Probleme tauchen auf, wenn ich mehr als eine Nachricht sende, aber es ist bizarrer als das.Mehrere iPhone APN-Nachrichten, einzelne Verbindung

Ich teste mit mehreren Geräten ... einige iPhones und einige iPod Touches. Ich kann mehrere Nachrichten ohne Probleme an die iPhones senden, aber wenn ich eine iPod Touch-Geräte-ID in der Liste habe, wird jede Nachricht fehlschlagen.

Also, wenn ich senden 4 Nachrichten in der Reihenfolge wie folgt aus:

1 - iPhone
2 - iPhone
3 - iPod-Note
4 - iPhone

1 und 2 geliefert wird, 3 und 4 scheitern.

Bei Verwendung derselben Geräte-IDs werden alle Nachrichten fehlgeschlagen, wenn ich eine der iPod Touch-Geräte-IDs als erste Nachricht verschiebe. Ebenso, wenn ich nur an iPhones sende, werden alle Nachrichten erfolgreich sein.

Hier ist der Code, mit dem ich testen, in seinem aktuellen Zustand, würde ich nur die ersten beiden Nachrichten erhalten, die letzten beiden werden jedes Mal fehlschlagen.

import struct, ssl, json, sys, time, socket, binascii 
from optparse import OptionParser 

class PushSender(object): 

    def __init__(self, host, cert, key): 
     self.apnhost = (host, 2195) 
     self.sock = ssl.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM), 
            keyfile = key, 
            certfile = cert, 
            do_handshake_on_connect=False) 
     self.sock.connect(self.apnhost) 
     while True: 
      try: 
       self.sock.do_handshake() 
       break 
      except ssl.SSLError, err: 
       if err.args[0] == ssl.SSL_ERROR_WANT_READ: 
        select.select([self.sock], [], []) 
       elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE: 
        select.select([], [self.sock], []) 
       else: 
        raise 

    def send_message(self, token, message): 
     payload = {'aps':{'alert':message}} 
     token = binascii.unhexlify(token) 
     payloadstr = json.dumps(payload, separators=(',',':')) 
     payloadLen = len(payloadstr) 
     fmt = "!BH32sH%ds" % payloadLen 
     notification = struct.pack(fmt, 0, 32, token, payloadLen, payloadstr) 
     self.sock.write(notification) 
     self.sock. 


    def close(self): 
     self.sock.close() 

def main(): 
    parser = OptionParser() 
    parser.add_option("-c", "--certificate", dest="cert", 
         metavar="FILE", 
         help="Certificate file",) 

    parser.add_option("-p", "--privatekey", dest="key", 
         metavar="FILE", 
         help="Key file",) 
    parser.add_option("--host", help="apn host", dest='host') 
    (options, args) = parser.parse_args() 

    sender = PushSender(options.host, options.cert, options.key) 

    iphone1 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 
    print 'Sending iPhone #1 a message.' 
    print sender.send_message(iphone1,'Hey iPhone #1.') 

    iphone2 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 
    print 'Sending iPhone #2 a message.' 
    print sender.send_message(iphone2,'Hey iPhone #2.') 

    ipod1 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 
    print 'Sending iPod #1 a message.' 
    print sender.send_message(ipod1,'Hey iPod #1.') 

    iphone3 = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 
    print 'Sending iPhone #3 a message.' 
    print sender.send_message(iphone3,'Hey iPhone #3.') 

    sender.close() 

if __name__=="__main__": 
    main() 

Jede Hilfe willkommen ...

Antwort

14

Apple wird Ihre Verbindung lautlos fallen würde, wenn es einen ungültigen Geräte Token oder eine Nachricht empfängt, die zu lang ist. Die nächsten paar Nachrichten danach werden fehlschlagen, weil sie einfach nur in den Äther geschickt werden - die Verbindung ist geschlossen, aber das TCP-Fenster ist nicht erschöpft.

Bei Urban Airship, wo ich arbeite, haben wir einen Debug-Modus zu verwenden, wenn Menschen ihre Anwendungen mit Push auf unseren Service testen. Dies wird nach dem Senden einer Nachricht ein wenig anhalten, um sicherzustellen, dass dies nicht das Problem war - wenn die Verbindung abbricht, wissen wir, dass es sich um ein Problem mit dem Geräte-Token handelt, und melden einen Fehler als solchen. Eine ähnliche Methode könnte ein guter Weg sein, um zu überprüfen, ob dies der Fall ist oder nicht. Offensichtlich wird dadurch der Durchsatz gekappt und wir empfehlen es daher nicht für eine Produktionsumgebung.

+0

Michael, danke für die ausführliche Antwort, ich vermute, du hast Recht. Dieses Problem rührt von der Tatsache her, dass wir alle Geräte-Token eines Benutzers speicherten, um mehrere Geräte pro Benutzer zu unterstützen. Da wir ein Geräte-Token an eine Benutzer-ID anschlossen, statt einer eindeutigen Geräte-ID, haben wir die Möglichkeit eingeführt Ungültige Token werden gespeichert, da sich ein Geräte-Token ändern kann. – Sangraal

+0

Danke, dass Sie mir einen Weg vorgeschlagen haben, die Token, die wir bereits haben, auf ihre Gültigkeit zu testen. Das war ein anderes Problem, um das ich mir Sorgen machte. Ich habe bemerkt, dass beim Senden vieler Nachrichten mit einem ungültigen Geräte-Token die Verbindung einige Nachrichten später fallen würde. Das ist das Verhalten, das Sie oben beschreiben. – Sangraal

+0

Ich sollte auch hinzufügen, dass Apple ein Token für Entwicklungsgeräte, das an einen Produktionsserver gesendet wird, als ungültiges Token betrachtet (und umgekehrt). Dieses Problem tritt ziemlich häufig auf, wenn Sie Entwicklungsgerätetoken und Produktionsgerätetoken mischen. Hoffe, das hilft! –

Verwandte Themen