2009-11-18 9 views
6

Tengo un problema extraño. Estoy intentando que Apple Push Notifications funcione con Python. Puedo conectar y enviar mensajes individuales sin ningún problema. Los problemas aparecen cuando comienzo a enviar más de un mensaje, pero es más extraño que eso.Múltiples mensajes de iPhone APN, conexión única

Estoy probando con varios dispositivos ... algunos iPhones y algunos iPod Touch. Puedo enviar múltiples mensajes a los iPhones sin problemas, pero si tengo una identificación de dispositivo iPod Touch en la lista, cualquier mensaje que ocurra fallará.

Así que si envío 4 mensajes en secuencia como esta:

1 - iPhone
2 - iPhone
3 - iPod Touch
4 - iPhone

1 y 2 serán entregados, 3 y 4 fallan

Usando las mismas ID de dispositivo, si muevo cualquiera de las ID del dispositivo iPod Touch para que sea el primer mensaje, todos los mensajes fallarán. Del mismo modo, si solo envío a iPhones, todos los mensajes tendrán éxito.

Aquí está el código que estoy probando, en su estado actual, solo recibiría los dos primeros mensajes, los dos últimos fallarán siempre.

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

Cualquier ayuda se agradece ...

Respuesta

14

Apple va a caer en silencio su conexión si recibe un dispositivo no válido símbolo o un mensaje que es demasiado larga. El siguiente par de mensajes después de eso fallará porque simplemente se envían al éter, esencialmente: la conexión está cerrada, pero la ventana TCP no está agotada.

En Urban Airship, donde trabajo, tenemos un modo de depuración para usar cuando las personas prueban sus aplicaciones con nuestro servicio. Esto se pausará un poco después de enviar un mensaje para garantizar que este no sea el problema: si la conexión se cae, sabemos que es un problema con el token del dispositivo e informamos un error como tal. Un método similar podría ser una buena forma de verificar si esto es o no lo que está sucediendo. Obviamente, esto elimina el rendimiento, por lo que no lo recomendamos para un entorno de producción.

+0

Michael, gracias por la respuesta detallada, sospecho que tiene razón. Este problema se debió al hecho de que estábamos almacenando todos los tokens de dispositivo de un usuario en un intento de admitir varios dispositivos por usuario, ya que estábamos adjuntando un token de dispositivo a un ID de usuario en lugar de un ID de dispositivo único, presentamos la posibilidad de se almacenan tokens inválidos ya que un token de dispositivo puede cambiar. – Sangraal

+0

Además, gracias por sugerir una forma en que puedo probar los tokens que ya tenemos para la validez, ese fue otro problema que me preocupaba. Me he dado cuenta al enviar muchos mensajes con un token de dispositivo no válido primero, la conexión soltaría algunos mensajes más tarde. Ese es el comportamiento que describes arriba. – Sangraal

+0

También debo agregar que Apple considera que un token de dispositivo de desarrollo enviado a un servidor de producción es un token de dispositivo no válido (y viceversa). Este problema aparece con bastante frecuencia, entonces, si mezcla tokens de dispositivo de desarrollo y tokens de dispositivo de producción. Espero que esto ayude! –

Cuestiones relacionadas