Raspberry + socket.io 在本地网络上工作,但不能从外部网络工作
Raspberry + socket.io works on local network but not from outside
我有一个 Raspberry Pi 通过 server.js 文件为 html 页面提供服务。主线(不是所有的代码)是:
var app = require('http').createServer(handler);
var io = require('socket.io').listen(app);
...
app.listen(8000);
...
fucntion handler(req,res) {
fs.readFile(__dirname+'/../index.html' function(err,data) {
...
io.sockets.on('connection', function (socket) {
setInterval(function(){
...
socket.emit('tempUpd',date,temp);
}, 2000);
});
在 index.html:
<head>
...
<script src="/socket.io/socket.io.js"></script>
...
</head>
<body>
<div id="info"></div>
---
<script>
var socket = io.connect('http://192.168.1.6:8000');
socket.on('tempUpd', function(date, temp){
document.getElementById("info").textContent = temp;
});
...
</script>
</body>
</html>
如您所见,我们的想法是每 2 秒更新一次温度测量值。
当我通过本地网络(使用无线)从智能手机连接到 Raspberry PI 时,一切正常,我可以访问网页并查看每 2 秒变化一次的温度值。
当我关闭智能手机上的无线并通过移动网络连接到 Raspberry(已将我的路由器配置为允许连接传递到 raspberry pi)时,我可以看到网页,但是通过套接字传递的所有信息永远不会显示。
考虑到由于某种原因我无法在该页面上看到动态元素,我添加了另一个 ,并添加了一些代码,以便它使用 setInterval 每 2 秒显示一次当前时间。我看到时间在变化,但没有显示通过套接字的任何内容。再次,我切换到本地网络,一切都可见,包括通过套接字传递的信息。
知道会发生什么吗?
非常感谢!!
192.168.1.6
是本地网络地址。您无法从本地网络外部访问该地址。移动网络在您的本地网络之外。当您从 phone 使用 WiFi 时,您正在连接到本地网络内的接入点,然后您可以路由到 192.168.1.6
。
要从 public 移动网络(从您自己的本地网络外部)访问它,您必须有一个从本地网络外部路由到您的服务器的 public IP 地址.
解决此问题的常用方法是为您的互联网连接获取一个 public IP 地址(或使用动态 DNS 获取 DHCP 分配的地址),然后在您的互联网路由器上配置 "port forwarding"。这将接收发往您 public IP 地址上特定端口的传入数据包,并将它们转发到您内部网络上的特定设备(例如您的 Raspberry Pi)。
您需要更新 index.html 页面以根据节点服务器的 IP 地址动态打开您的套接字。正如其他人指出的那样,当您从互联网连接到服务器时,您的 Pi 不在 192.168.1.6。 (那是你的本地网络)
如果您能够访问该网页,则说明您的路由器正在正确转发内容。
在您的 index.html 页面上,将以下行更改为:
var socket = io.connect('http://192.168.1.6:8000');
至:
var socket = io.connect('http://' + location.host + ':8000');
还要确保您也将路由器上的端口 8000 转发到您的 Pi。
祝你好运。
--埃德
我有一个 Raspberry Pi 通过 server.js 文件为 html 页面提供服务。主线(不是所有的代码)是:
var app = require('http').createServer(handler);
var io = require('socket.io').listen(app);
...
app.listen(8000);
...
fucntion handler(req,res) {
fs.readFile(__dirname+'/../index.html' function(err,data) {
...
io.sockets.on('connection', function (socket) {
setInterval(function(){
...
socket.emit('tempUpd',date,temp);
}, 2000);
});
在 index.html:
<head>
...
<script src="/socket.io/socket.io.js"></script>
...
</head>
<body>
<div id="info"></div>
---
<script>
var socket = io.connect('http://192.168.1.6:8000');
socket.on('tempUpd', function(date, temp){
document.getElementById("info").textContent = temp;
});
...
</script>
</body>
</html>
如您所见,我们的想法是每 2 秒更新一次温度测量值。
当我通过本地网络(使用无线)从智能手机连接到 Raspberry PI 时,一切正常,我可以访问网页并查看每 2 秒变化一次的温度值。
当我关闭智能手机上的无线并通过移动网络连接到 Raspberry(已将我的路由器配置为允许连接传递到 raspberry pi)时,我可以看到网页,但是通过套接字传递的所有信息永远不会显示。
考虑到由于某种原因我无法在该页面上看到动态元素,我添加了另一个 ,并添加了一些代码,以便它使用 setInterval 每 2 秒显示一次当前时间。我看到时间在变化,但没有显示通过套接字的任何内容。再次,我切换到本地网络,一切都可见,包括通过套接字传递的信息。
知道会发生什么吗? 非常感谢!!
192.168.1.6
是本地网络地址。您无法从本地网络外部访问该地址。移动网络在您的本地网络之外。当您从 phone 使用 WiFi 时,您正在连接到本地网络内的接入点,然后您可以路由到 192.168.1.6
。
要从 public 移动网络(从您自己的本地网络外部)访问它,您必须有一个从本地网络外部路由到您的服务器的 public IP 地址.
解决此问题的常用方法是为您的互联网连接获取一个 public IP 地址(或使用动态 DNS 获取 DHCP 分配的地址),然后在您的互联网路由器上配置 "port forwarding"。这将接收发往您 public IP 地址上特定端口的传入数据包,并将它们转发到您内部网络上的特定设备(例如您的 Raspberry Pi)。
您需要更新 index.html 页面以根据节点服务器的 IP 地址动态打开您的套接字。正如其他人指出的那样,当您从互联网连接到服务器时,您的 Pi 不在 192.168.1.6。 (那是你的本地网络)
如果您能够访问该网页,则说明您的路由器正在正确转发内容。
在您的 index.html 页面上,将以下行更改为:
var socket = io.connect('http://192.168.1.6:8000');
至:
var socket = io.connect('http://' + location.host + ':8000');
还要确保您也将路由器上的端口 8000 转发到您的 Pi。
祝你好运。
--埃德