python - 以最少的数据使用量推送通知

标签 python web push-notification connection network-protocols

在我的项目中,我想从互联网上调用 Raspberry Pi 上的操作。不知怎么的:

  1. 访问网页
  2. 点击网页上的按钮
  3. Raspberry pi 执行脚本

困难的部分是,树莓派只有移动互联网连接没有固定费率。因此,向 Raspberry Pi 发送和接收数据的成本很高。

这就是我的问题:

我可以使用哪些技术和模式以最少的数据使用量向树莓派发送推送通知?

最佳答案

首先在 RPi 上创建或启动接受传入连接的程序。像下面的例子这样的小东西就可以做到:

#!/usr/bin/python
from socket import *
s = socket()
s.bind(('', 8001))
s.listen(4)
while 1:
    ns, na = s.accept()
    print(na,'sent you:',ns.recv(8192))

现在,上面的示例将只打开 8001 上的端口,然后打印其他发送到它的任何内容。

在服务器端,我建议您设置一个网络服务器或其他易于访问的东西,可以将IP存储在数据库中/在某个地方注册。

然后,在 RPi 启动期间(首选网络服务启动后)继续并安排:

curl https://your-server.eu/reg_ip.php > /dev/null 2>&1

现在,在服务器 your-server.eu:443 上,确保 req_ip.php 将客户端 IP(客户端是您的 RPi)保存在数据库中的某个位置。

现在,您需要发送推送通知的应用程序可以在数据库中查找客户端的当前 IP,并尝试连接到这些 IP 上的端口 8001 并发送您想要的任何数据需要。

现在有两件事:

  1. 监听 TCP 套接字(在 RPi 上)根本不会使用任何数据,但会在需要时允许传入连接。

  2. 如果您的 RPi 上的 IP 发生变化(例如,在移动的 GSM/3G/4G 网络上可能会发生变化),您需要向您的服务器发出另一个 curl 请求。然而,这可以很容易地绑定(bind)到例如ip监视命令,然后执行curl请求。

tl;博士

这是您的链条:

Pi 打开监听套接字 -> Pi 连接到 HTTP(S) -> 服务器保存 IP -> 当服务器有数据要发送时 -> 连接到端口 X 上的最后一个已知 IP -> 发送数据 -> 关闭连接

进一步增强

现在,仅 HTTP header 就相当大,事实上它是默认的 78 字节的包数据(TCP 和 IP header 通常不包含在数据速率中,只有正在传输的数据 - 在本例中为 HTTP 数据。 )。因此,您可以扩展的是,如果您也可以在服务器上使用上面的套接字的简单示例,只需获取 na[0] 变量并将其发送到数据库,这样您就可以使用您的数据订阅的数据速率实际上为 0。

只有稍后从服务器应用程序作为“推送通知”发送的实际数据才会耗尽数据。

如果您的 RPi 位于基于 NAT 的网络(专用网络)

当 OP 获取 10.X.X.X 地址时,监听套接字不太可能实现这一目的。

相反,您可以简单地尝试建立连接并保持其打开状态,并让服务器在有数据时通过任何打开的套接字发送数据。

这里有一个关于如何实现它的非常粗略的想法。
我保持简单和愚蠢只是为了提供一个想法而没有解决整个问题。

同样,在您实际通过 channel 发送数据之前,客户端 (RPi) 和服务器之间的打开套接字不会使用任何数据。

您可以在服务器中从数据库中获取要发送给客户端的数据,您实际上可以做任何事情。由于我不知道你的目标,所以暂时保持原样。

服务器:

#!/usr/bin/python
from socket import *
from threading import *
from time import time, sleep
from random import randint

class ClientThread(Thread)
    def __init__(self, clients):
        self.clients = clients
        self.messages = []
        Thread.__init__(self)
        self.start()

    def notify(self, message):
        if type(message) is str: message = bytes(message, 'UTF-8')
        self.messages.append(message)

    def run(self):
        while 1:
            if len(self.messages) > 0:
                m = self.messages.pop(0)
                for client in self.clients:
                    self.clients[client]['sock'].send(m)

class RandomMessageGenerator(Thread):
    def __init__(self, notify_func):
        self.notify_func = notify_func
        self.last = time()
        Thread.__init__(self)
        self.start()

    def run(self):
        while 1:
            self.notify_func('Time since last update: ' + str(time() - self.last))
            self.last = time()
            sleep(randint(0,30))

client_list = {}
client_thread_handle = ClientThread(client_list)
random_generator = RandomMessageGenerator(client_thread_handle.nofity)

s = socket()
s.bind(('', 8001))
s.listen(4)

while 1:
    ns, na = s.accept()
    client_list[na] = {'sock' : 'ns'}

客户端:

from socket import *
s = socket()
s.connect(('server', 8001))
while 1:
    print(s.recv(8192))

关于python - 以最少的数据使用量推送通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39699461/

相关文章:

rest - 我应该如何使用 Keycloak 设置 "role-less"(ACL、ABAC)REST API 的授权?

php - 用于签署推送通知 token 的 Apple 签名 key 的 x、y 和曲线参数是什么?

javascript - Web 推送通知脚本适用于 Firefox 但不适用于 Chrome

python - 如何在Python中将磅转换为千克

python - 如何将数据重定向到 "getpass"之类的密码输入?

javascript - 如何检查加载时卡住的网站?

php - 在我的 Laravel 网站上集成 WordPress 博客的最佳方式是什么?

python - Pandas 验证日期格式

python - 更新列中的值

Java Sockets - 在没有输入流的情况下检测网络断开连接