2009-11-18 14 views
6

Ho uno strano problema. Sto cercando di ottenere notifiche push Apple che funzionano con Python. Posso connettere e inviare singoli messaggi senza problemi. I problemi si presentano quando inizio a inviare più di un messaggio, ma è più bizzarro di quello.Più messaggi APN per iPhone, connessione singola

Sto testando con più dispositivi ... alcuni iPhone e alcuni iPod Touch. Posso inviare più messaggi all'iPhone senza intoppi, ma se ho un ID dispositivo iPod Touch nell'elenco, tutti i messaggi successivi falliranno.

Quindi, se io mando 4 messaggi in sequenza come questo:

1 - iPhone
2 - iPhone
3 - ipod touch
4 - iPhone

1 e 2 sarà consegnato, 3 e 4 falliscono.

Utilizzando lo stesso ID dispositivo, se si sposta uno qualsiasi degli ID dispositivo iPod Touch per essere il primo messaggio, tutti i messaggi non riusciranno. Allo stesso modo, se invio solo su iPhone, tutti i messaggi avranno successo.

Ecco il codice che sto testando, nel suo stato attuale, otterrei solo i primi due messaggi, gli ultimi due falliranno ogni volta.

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() 

Qualsiasi aiuto sarebbe apprezzato ...

risposta

14

Apple silenziosamente cadere la connessione se si riceve un dispositivo valido simbolico o un messaggio che è troppo lungo. Il prossimo paio di messaggi successivi fallirà perché sono semplicemente inviati nell'etere, essenzialmente - la connessione è chiusa, ma la finestra TCP non è esaurita.

In Urban Airship, dove lavoro, abbiamo una modalità di debug da utilizzare quando le persone testano le loro applicazioni con la spinta sul nostro servizio. Questo si interromperà per un po 'dopo l'invio di un messaggio per garantire che questo non sia il problema - se la connessione si interrompe, sappiamo che si tratta di un problema con il token del dispositivo e segnala un errore in quanto tale. Un metodo simile potrebbe essere un buon modo per verificare se questo è, o meno, cosa sta succedendo. Ovviamente questo uccide il throughput e quindi non lo consigliamo per un ambiente di produzione.

+0

Michael, grazie per la risposta dettagliata, ho il sospetto che tu abbia ragione. Questo problema deriva dal fatto che stavamo memorizzando tutti i token di dispositivo di un utente nel tentativo di supportare più dispositivi per utente, dal momento che stavamo collegando un token di dispositivo a un ID utente piuttosto che un id univoco, abbiamo introdotto la possibilità di i token non validi vengono archiviati poiché un token dispositivo può essere modificato. – Sangraal

+0

Inoltre, grazie per avermi suggerito un modo per testare i token che abbiamo già per validità, quello era un altro problema di cui ero preoccupato. Ho notato che durante l'invio di molti messaggi con un token dispositivo non valido per primo, la connessione avrebbe lasciato cadere alcuni messaggi in un secondo momento. Questo è il comportamento che stai descrivendo sopra. – Sangraal

+0

Devo anche aggiungere che Apple considera un token dispositivo di sviluppo inviato a un server di produzione come token dispositivo non valido (e viceversa). Questo problema si presenta abbastanza spesso, quindi, se si combinano token dispositivo di sviluppo e token dispositivo di produzione. Spero che questo aiuti! –

Problemi correlati