Несколько сообщений iPhone APN, одно соединение - PullRequest
6 голосов
/ 19 ноября 2009

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

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

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

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

Буду признателен за любую помощь ...

1 Ответ

14 голосов
/ 19 ноября 2009

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

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

...