Python APNs 不处理请求

1 投票
3 回答
1609 浏览
提问于 2025-04-16 10:51

我正在尝试实现一个服务器端的脚本,用来向苹果推送通知服务器发送推送通知。我建立了SSL连接,发送了数据包,但却无法从苹果推送通知服务器收到回应。以下是我的代码:

import socket, ssl, pprint, struct, time, binascii

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# require a certificate from the server
ssl_sock = ssl.wrap_socket( s,
                            keyfile="/Users/Jeff/Desktop/pickmeup-key2-noenc.pem",
                            certfile="/Users/Jeff/Desktop/pickmeup-cert2.pem",
                            server_side=False,
                            do_handshake_on_connect=True,
                            cert_reqs=ssl.CERT_REQUIRED,
                            ca_certs="/Users/Jeff/Desktop/entrustrootcert.pem",)
                            #ciphers="ALL")
ssl_sock.connect(('gateway.sandbox.push.apple.com', 2195))

print repr(ssl_sock.getpeername())
print ssl_sock.cipher()
print pprint.pformat(ssl_sock.getpeercert())

command = '\x00'
identifier = 1987
expiry = time.time()
deviceToken = "9858d81caa236a86cc67d01e1a07ba1df0982178dd7c95aae115d033b93cb3f5"
alert = "This is a test message"
sound = "UILocalNotificationDefaultSoundName"
payload = "{\"aps\":{\"alert\":\"%s\",\"sound\":\"%s\"}}" %(alert, sound)

packetFormat = "!cIIH%dsH%ds" %(32, len(payload))

packet = struct.pack(packetFormat, 
                    command, 
                    identifier,
                    int(expiry),
                    32, 
                    binascii.unhexlify(deviceToken), 
                    len(payload), 
                    payload)
nBytesWritten = ssl_sock.write(packet)
print "nBytesWritten = %d" %(nBytesWritten)

data = ssl_sock.read(1024)
print len(data)

ssl_sock.close()

运行这个脚本后,我得到了以下输出:

('17.149.34.132', 2195)
('AES256-SHA', 'TLSv1/SSLv3', 256)
{'notAfter': 'May 31 00:04:27 2012 GMT',
 'subject': ((('countryName', u'US'),),
             (('stateOrProvinceName', u'California'),),
             (('localityName', u'Cupertino'),),
             (('organizationName', u'Apple Inc'),),
             (('organizationalUnitName', u'Internet Services'),),
             (('commonName', u'gateway.sandbox.push.apple.com'),))}
nBytesWritten = 133
0

有没有人知道可能出什么问题了?(因为我发送的是增强型推送通知,所以我期待能从苹果推送通知服务器收到回应)

3 个回答

-3

苹果的推送通知服务器不提供响应,它是一个单向的二进制连接。这意味着你发送消息过去,但不会收到回复。与其自己去开发一个解决方案,不如试试apns-python-wrapper或者apns这些现成的工具。

0

你可以考虑一下这个链接:https://github.com/djacobs/PyAPNs,它包含了很多实用的功能,具体包括:

  • 错误处理
  • 支持增强的消息格式,并且可以自动重新发送在出现错误响应之前发送的消息
  • 非阻塞的SSL套接字连接,性能非常好
4

这里要注意的关键点是,read() 没有返回任何数据。在 Python 中,read() 应该会一直等待,直到有数据可用或者连接关闭。苹果正在关闭你的连接。

为什么会这样呢?可能是因为你发送了一个格式不正确的请求。command=0 是正常的推送通知;而 command=1 是增强版的。大端格式的 1987 会被解释为一个 0 字节的设备令牌和一个 1987 字节的有效载荷,这两者都是无效的。

(顺便说一下,我建议用 B 来表示命令 ID,而不是 c;这样似乎更合理。)

撰写回答