向路由器后面的设备发送 HTTP 请求

Posted

技术标签:

【中文标题】向路由器后面的设备发送 HTTP 请求【英文标题】:Send HTTP Request to a device behind router 【发布时间】:2014-02-27 09:17:50 【问题描述】:

我有一个连接到路由器后面的家庭网络的设备,它需要接收激活某些功能的请求。

我现在这样做的方式是我在路由器中设置了端口转发,它处理这些外部请求并将它们转发到设备。

据我所知,另一种方法是保持与服务器的开放套接字连接并不断收听这些消息,但我会尽量避免这种情况,因为数据传输每天发生一次并且持续保持开放的连接会消耗宝贵的服务器资源。

我仍然需要发送此数据和要触发的设备同时将数据传递给它。

我也考虑过每 5 分钟左右从设备中提取新消息,但那样我就失去了实时效果。

需要编写一个可以扩展以与至少 10 000 台此类设备通信的服务器。最好用 Ruby on Rails 或 Node.js 之类的东西编写。

平均每天发送一次请求作为一条小消息。

那么实现这一目标的最佳选择是什么?考虑在不久的将来扩展,我如何从服务器“推送”到设备?

编辑:

将设备视为开/关开关。该开关可以在实际设备上手动翻转,也可以由服务器远程触发。当手动触发时,它将负责将状态传播到服务器,当被远程触发时,它应该侦听并响应来自服务器的消息,该消息可能随时发生(因此设备无法每隔一段时间 ping 服务器以获取状态,需要是实时的)。

【问题讨论】:

客户端是什么设备/操作系统? 它是一个微控制器。支持 Http 请求,我没有构建它,但我很确定它可以处理套接字,不确定是否有 websockets 库。 为你写答案 【参考方案1】:

你可以将 Rails 用于数据处理系统(存储消息等)

昨晚我在想这件事:

    Rails 将创建一系列endpoints 当您的“设备”想要通信时,它必须向端点发起请求 设备将推送到 Rails 端点

设备

在不知道设备是什么的情况下,我想象它的工作方式是它必须能够在发生某些事情时发起 POST 请求(想象 Rasberry Pi 发送数据)

如果您的设备是牙刷,则您必须具备(芯片上或外部)功能才能连接到网络并将数据发送到您的(插入框架)服务器


导轨

Rails 可以这样处理(这是我们的一些实时分析系统代码,其工作方式类似):

#config/routes.rb
post "/update", to: "messages#create"

#app/controllers/messages_controller.rb
protect_from_forgery with: :null_session    
before_action :authenticate

#Data
def create
    #create message here
end

private

# have to give x a "token" 
def authenticate 
authenticate_or_request_with_http_token do |token, options|
    user = User.exists?(public_key: token)
    @token = token if user
end
end

这将创建端点:

domain.com/update

您必须在标头中发送您的authentication token,并且可能需要使用rack-CORS(或另一个CORS 策略管理器)来处理x 域事务:

#config/application.rb
config.middleware.use Rack::Cors do
    allow do
        origins '*'
        resource '/update*', :headers => :any, :methods => :post
    end
end

数据

Rails 的东西是 MVC application(可以根据您的后端服务器资源进行扩展)

当您想将设备集成到后端时,棘手的部分就来了。你提到你可以支持http请求——诀窍是“如何”

    您必须集成一些身份验证(可能是序列号),这些身份验证必须存在于您的 Rails 数据库中 然后这将通过设备通过网络发送到您的端点 收到请求后,Rails 可以在服务器上处理它并返回响应

所以最大的问题是——您的设备将如何与服务器通信?


交叉沟通

Server -> Device通讯为push technology:

    设备将 ping “直播”(通过浏览器中的 JS,在其他浏览器中不确定) 服务器会将数据发送到特定的“通道” 如果设备订阅了频道,它将收到更新

问题不在于“网络套接字”技术,而在于"sub/pub"

在浏览器世界中,您基本上会打开与 javascript 的永久连接。这可以通过使用SSE's(美化long-polling)或websockets来完成

两者都可以通过“收听”您频道上的事件来访问:

#Pusher
channel.bind('my-event', function(data) 
  alert('An event was triggered with message: ' + data.message);
);

#SSE's
var source = new EventSource("demo_sse.php");
source.onmessage = function(event) 
  document.getElementById("result").innerhtml + =event.data + "<br>";
;

就您的设备而言,我会查看您希望从服务器接收数据的频率。当然,发送数据是一种“按需”服务,但正如你所说,接收确实会带来开销

如果您只希望每天收到一条消息,我会考虑使用某种long-polling 技术每隔x 小时查找一次数据;如果您立即需要该消息,我会考虑将持久连接与 Web 套接字集成


服务器

在服务器上处理这个将归结为您的服务器可以处理多少并发连接

如果您使用 AWS,您将能够相对简单地进行扩展,但每个连接都将被归类为“并发”

【讨论】:

在设备 -> 服务器通信方面,我的想法是相同的。该设备完全有能力做你描述的事情。它是一个连接到路由器的盒子,用于传输射频信号。我对另一种方式很好奇。服务器如何将消息推送到路由器后面的设备。所以服务器 - >设备。据我所知,设备必须是必须打开连接的设备,否则服务器无法访问它。 如果您提交 POST 请求,该请求的 response 将直接发送到设备(就像浏览器的工作方式一样)。然而,如果你想send来自服务器的消息,你将不得不使用类似网络套接字(Pusher)技术 如果你愿意,我可以写一些相关的信息吗? 是的,我愿意。谢谢!我可以弄清楚设备 -> 服务器,但我没有使用 Web 套接字保持持久连接以及在需要这么多连接的系统中如何扩展的经验。并且对于需要每天联系一次的东西保持实时连接似乎是一种开销,向它发送类似 100 字节的数据。 是的,这将是一个开销,因此我写这篇文章的原因是,将技术重点放在向服务器发送数据而不是相反是有益的。我现在就为你写下我对 websockets 的了解

以上是关于向路由器后面的设备发送 HTTP 请求的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Telnet 发送 HTTP 请求 [关闭]

如何从两个不同的路由/网址收集数据,然后在最后使用收集的数据向服务器发送请求?

Laravel CSRF 令牌不匹配异常。通过 jQuery ajax 向资源路由发送“Put”请求

HTTP协议

tp路由器登陆不了。老是发送请求失败

我一直在尝试打孔并将数据报发送到路由器后面的朋友计算机,但没有任何反应