多个 iPhone APN 消息,单个连接

发布于 2024-08-11 15:16:53 字数 3144 浏览 3 评论 0原文

我有一个奇怪的问题。我正在尝试让 Apple 推送通知与 Python 一起使用。我可以毫无问题地连接并发送单独的消息。当我开始发送多条消息时,问题就会出现,但比这更奇怪。

我正在使用多个设备进行测试...一些 iPhone 和一些 iPod Touch。我可以顺利地向 iPhone 发送多条消息,但如果列表中有 iPod Touch 设备 ID,则后续发送的任何消息都会失败。

因此,如果我按如下顺序发送 4 条消息:

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

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

使用相同的设备 ID,如果我将任何 iPod Touch 设备 ID 移动为第一条消息,则所有消息都将失败。同样,如果我只发送到 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()

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

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.

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.

So if I send 4 messages in sequence like this:

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

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

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...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

赠我空喜 2024-08-18 15:16:53

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

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

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.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文