2009-11-18 2 views
6

У меня странная проблема. Я пытаюсь заставить Apple Push Notifications работать с Python. Я могу подключать и отправлять отдельные сообщения без проблем. Проблемы возникают, когда я начинаю отправлять несколько сообщений, но это более странно, чем это возможно.Несколько сообщений APN iPhone, одно соединение

Я тестирую несколько устройств ... некоторые iPhone и некоторые iPod Touch. Я могу отправить несколько сообщений на iPhone без заминки, но если у меня есть идентификатор устройства iPod Touch в списке, любое сообщение, которое будет после этого, не удастся.

Так что, если я посылаю 4 сообщения в последовательности, как это:

1 - картинки
2 - iPhone
3 - Ipod Touch
4 - iPhone

1 и 2 будут доставлены, 3 и 4 сбой.

Использование одних и тех же идентификаторов устройства, если я переведу любой идентификатор устройства iPod Touch в качестве первого сообщения, все сообщения не удастся. Аналогично, если я только отправлю на iPhone, все сообщения будут успешными.

Вот код, который я тестирую, в текущем состоянии, я бы получил только первые два сообщения, последние два будут терпеть неудачу каждый раз.

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

Любая помощь будет оценена ...

ответ

14

Apple, молча уроните соединение, если оно получает недопустимое устройство маркер или сообщение, что это слишком долго. Следующие несколько сообщений после этого потерпят неудачу, потому что они просто отправлены в эфир, по сути - соединение закрыто, но окно TCP не исчерпывается.

На городском дирижабле, где я работаю, у нас есть режим отладки, который нужно использовать, когда люди проверяют свои приложения с помощью нашего сервиса. Это немного остановится после отправки сообщения, чтобы убедиться, что это не проблема. Если соединение падает, мы знаем, что это проблема с токеном устройства и сообщают об ошибке как таковой. Подобный метод может быть хорошим способом проверить, что это или нет, что происходит. Очевидно, что это убивает пропускную способность, и поэтому мы не рекомендуем его для производственной среды.

+0

Майкл, спасибо за подробный ответ, я подозреваю, что вы правы. Эта проблема возникла из-за того, что мы хранили все токены устройства пользователя, пытаясь поддерживать несколько устройств на пользователя, поскольку мы прикрепляли токен устройства к идентификатору пользователя, а не уникальный идентификатор устройства, мы ввели возможность недействительные токены, которые сохраняются, поскольку токен устройства может измениться. – Sangraal

+0

Кроме того, благодарю вас за то, что вы предлагаете способ, которым я могу проверить токены, которые у нас уже есть для действительности, это была еще одна проблема, о которой я беспокоился. Я заметил, что при отправке многих сообщений с недействительным маркером устройства сначала соединение будет удалять несколько сообщений позже. Это поведение, которое вы описываете выше. – Sangraal

+0

Я также должен добавить, что Apple рассматривает маркер устройства разработки, отправленный на производственный сервер, как недействительный токен устройства (и наоборот). Эта проблема возникает довольно часто, тогда, если вы смешиваете маркеры маркеров разработки и токены производственных устройств. Надеюсь, это поможет! –