多条 iPhone APN 消息,单次连接 [英] Multiple iPhone APN messages, single connection

查看:25
本文介绍了多条 iPhone APN 消息,单次连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个奇怪的问题.我正在尝试让 Apple 推送通知与 Python 一起工作.我可以毫无问题地连接和发送单独的消息.当我开始发送不止一条消息时会出现问题,但比这更奇怪.

I have a strange issue. I'm trying to get Apple Push Notifications working with Python. I can connect and send individual messages without a problem. The issues pop up when I start sending more than one message, but it's more bizarre than even that.

我正在使用多种设备进行测试……一些 iPhone 和一些 iPod Touch.我可以毫不费力地向 iPhone 发送多条消息,但如果列表中有 iPod Touch 设备 ID,则之后的任何消息都将失败.

I'm testing with multiple devices... some iPhones and some iPod Touches. I can send multiple messages to the iPhones without a hitch, but if I have an iPod Touch device id in the list, any message that goes after will fail.

所以如果我像这样按顺序发送 4 条消息:

So if I send 4 messages in sequence like this:

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

1 - iPhone
2 - iPhone
3 - ipod Touch
4 - iPhone

1 和 2 将交付,3 和 4 失败.

1 and 2 will be delivered, 3 and 4 fail.

使用相同的设备 ID,如果我将任何 iPod Touch 设备 ID 移到第一条消息,所有消息都将失败.同样,如果我只发送到 iPhone,所有消息都会成功.

Using the same device ID's, if I move any of the iPod Touch device ID's to be the first message, all messages will fail. Likewise, if I only send to iPhones, all messages will succeed.

这是我正在测试的代码,在当前状态下,我只会收到前两条消息,后两条消息每次都会失败.

Here's the code I'm testing with, in it's current state, I would only get the first two messages, the last two will fail every time.

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

任何帮助将不胜感激...

Any help would be appreciated...

推荐答案

如果 Apple 收到无效的设备令牌或太长的消息,它会悄悄断开您的连接.之后的接下来的几条消息将失败,因为它们只是被发送到以太坊中,本质上 - 连接已关闭,但 TCP 窗口并未耗尽.

Apple will silently drop your connection if it receives an invalid device token or a message that's too long. The next couple of messages after that will fail because they're just sent into the ether, essentially - the connection is closed, but the TCP window isn't exhausted.

在我工作的 Urban Airship,当人们通过我们的服务推送测试他们的应用程序时,我们可以使用调试模式.这将在发送消息后暂停一段时间以确保这不是问题 - 如果连接断开,我们知道这是设备令牌的问题并报告错误.类似的方法可能是您检查这是或不是正在发生的事情的好方法.显然,这会降低吞吐量,因此我们不建议将其用于生产环境.

At Urban Airship, where I work, we have a debug mode to use when people test their applications with push on our service. This will pause for a little bit after sending a message to ensure that this wasn't the issue - if the connection drops, we know it's an issue with the device token and report an error as such. A similar method might be a good way for you to check that this is, or is not, what's going on. Obviously this kills throughput and so we don't recommend it for a production environment.

这篇关于多条 iPhone APN 消息,单次连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆