admin管理员组文章数量:1431691
Here's my setup:
Raspberry Pi 2 (192.168.1.101):
- Sensor recording temperature, pressure and humidity.
- Python3 script connected to a Raspberry Pi 3, reading sensor data and sending to Pi 3, in JSON format, every 5 seconds.
Raspberry Pi 3 (192.168.1.100):
- Node.js server listening for python client on port 8888.
- Socket.io listening for web clients on port 3000 (port 3000 and 80 have been opened on my router).
- Web server (on port 80) with a website displaying sensor data.
- JavaScript connecting to node server, using socket.io, via foobar.ddns:3000.
Misc:
- I'm using noip to have a domain serving my dynamic IP address, my router lets noip know when my public IP changes. I have a URL that looks like foobar.ddns.
This setup seems to be working. The Python script is sending data to the node server, which is forwarding it on to any web client connected, which is displayed correctly on the website.
My issue is that the web client disconnects after 1 round of ping/pong between the client and node server.
Here's the chrome console log when connected to the server and receiving data:
The web client connects, receives some data, does a ping/pong with the server, receives some more data, then when it's supposed to ping/pong again it disconnects, then after a while it tries reconnecting and the cycle continues.
And here's the node.js log:
The first New Connection is the Python client (I'm not sure why the IP is the Pi3 address), the rest are the same web client connecting, being disconnected for ping time out, then reconnecting. The client appears to be disconnecting based on on the servers pingInterval + pingTimeout values.
Changing the pingTimeout and pingInterval values just delays the disconnect.
Here's my code:
Python Client:
import json
import socket
import bme280_sensor
import time
import os
class Connection():
def __init__(self, host, port):
self.host = host
self.port = port
def connect(self):
print('Creating socket')
try:
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error as msg:
print('Failed to create socket: %s' % msg)
raise
print('Socket created')
server_address = (self.host, self.port)
print('Connecting to %s:%s' % server_address)
try:
self.sock.connect(server_address)
except socket.error as msg:
print('Failed to connect: %s' % msg)
raise
print('Connected')
def shutdown(self):
print('Shutting down')
self.sock.shutdown(socket.SHUT_RDWR)
self.sock.close()
def measure_temp():
bme_data = bme280_sensor.read_all()
obj = {}
obj['temp'] = round(bme_data[2], 2)
obj['humidity'] = round(bme_data[0], 2)
obj['pressure'] = round(bme_data[1], 2)
return json.dumps(obj)
def sendData(sock):
print('Sending data')
while True:
try:
data = 'data,' + measure_temp()
sock.sendall(data.encode())
except socket.error as msg:
print("Cannot send to server: %s" % msg)
break
time.sleep(5)
connection = Connection('192.168.1.100', 8888)
while True:
try:
connection.connect()
sendData(connection.sock)
connection.shutdown()
break
except socket.error as msg:
print('Connection failed, retrying in 3 seconds.')
time.sleep(3)
print('Done')
Node.js Server:
var net = require('net');
var port = 8888;
var server = net.createServer();
// socket io listens for clients on port 3000
var io = require('socket.io')(3000,{
pingInterval: 10000,
pingTimeout: 5000,
});
// server listens for python client on port 8888
server.listen(port);
console.log('Server started');
// store the last data recorded, so when a socket.io client connects, they can get the last reading instead of waiting for the next one
global.last;
server.on('connection', function(socket){
console.log('New server connection ' + socket.address().address);
// when the server recieves data, send it to the connected socket clients
socket.on('data', function(data){
// strip the first 5 characters from the input string, parse json from the result
var actual = generateJSON(data.toString().substring(5));
// store the dta
global.last = actual;
//send the data
io.sockets.emit('data', actual);
});
});
io.on('connection', function(socket){
console.log('New io connection ' + socket.id);
// if the server has data previously recorded, send it to the new client
if(global.last){
io.emit('data', global.last);
}
socket.on('disconnect', function(reason){
console.log('io disconnect: ' + reason);
});
});
function generateJSON(data){
var dataJSON = JSON.parse(data);
var obj = new Object();
obj.temperature = dataJSON.temp;
obj.humidity = dataJSON.humidity;
obj.pressure = dataJSON.pressure;
obj.datetime = new Date().toString();
return JSON.stringify(obj);
}
Website Javascript:
var socket;
var connected = false;
function connect(){
console.log('connecting...')
if(socket){
socket.destroy()
delete socket;
socket = null;
}
socket = io.connect(":3000", {
forceNew: true,
reconnection: true,
reconnectionDelay: 3000,
reconnectionDelayMax: 5000,
reconnectionAttempts: Infinity
});
console.log(socket);
socket.on("data", function(data){
var obj = JSON.parse(data);
console.log(data);
$('#temperature-value').text(obj.temperature);
$('#humidity-value').text(obj.humidity);
$('#pressure-value').text(obj.pressure);
lastUpdate = new Date();
});
socket.on('connect_error', function(error){
console.log('connection error: ' + error);
});
socket.on('connect_timeout', function(){
console.log('connection timeout');
});
socket.on('reconnect', function(){
console.log('reconnect');
});
socket.on('reconnect_attempt', function(){
console.log('reconnect attempt');
});
socket.on('reconnect_failed', function(){
console.log('reconnect_failed');
});
socket.on('reconnect_error', function(){
console.log('reconnect_error');
});
socket.on('reconnecting', function(){
console.log('reconnecting');
});
socket.on('ping', function(){
console.log('ping');
});
socket.on('pong', function(ms){
console.log('pong ' + ms + "ms");
});
socket.on('connect', function(){
console.log('connected to server');
connected = true;
});
socket.on('disconnect', function(reason){
console.log('disconnected from server: ' + reason);
connected = false;
});
}
$(document).ready(function(){
connect();
});
I'm accessing the socket.io.js script with this in my index.html:
<script src=":3000/socket.io/socket.io.js"></script>
This is functional but the disconnects are rather annoying, I'd rather the client stays connected. I have a feeling that my node.js server is not setup correctly, but I can't figure out what the issue is. If there's a better way to feed data from the python script > node.js server > web clients then please let me know.
Thanks
Here's my setup:
Raspberry Pi 2 (192.168.1.101):
- Sensor recording temperature, pressure and humidity.
- Python3 script connected to a Raspberry Pi 3, reading sensor data and sending to Pi 3, in JSON format, every 5 seconds.
Raspberry Pi 3 (192.168.1.100):
- Node.js server listening for python client on port 8888.
- Socket.io listening for web clients on port 3000 (port 3000 and 80 have been opened on my router).
- Web server (on port 80) with a website displaying sensor data.
- JavaScript connecting to node server, using socket.io, via foobar.ddns:3000.
Misc:
- I'm using noip. to have a domain serving my dynamic IP address, my router lets noip know when my public IP changes. I have a URL that looks like foobar.ddns.
This setup seems to be working. The Python script is sending data to the node server, which is forwarding it on to any web client connected, which is displayed correctly on the website.
My issue is that the web client disconnects after 1 round of ping/pong between the client and node server.
Here's the chrome console log when connected to the server and receiving data:
The web client connects, receives some data, does a ping/pong with the server, receives some more data, then when it's supposed to ping/pong again it disconnects, then after a while it tries reconnecting and the cycle continues.
And here's the node.js log:
The first New Connection is the Python client (I'm not sure why the IP is the Pi3 address), the rest are the same web client connecting, being disconnected for ping time out, then reconnecting. The client appears to be disconnecting based on on the servers pingInterval + pingTimeout values.
Changing the pingTimeout and pingInterval values just delays the disconnect.
Here's my code:
Python Client:
import json
import socket
import bme280_sensor
import time
import os
class Connection():
def __init__(self, host, port):
self.host = host
self.port = port
def connect(self):
print('Creating socket')
try:
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error as msg:
print('Failed to create socket: %s' % msg)
raise
print('Socket created')
server_address = (self.host, self.port)
print('Connecting to %s:%s' % server_address)
try:
self.sock.connect(server_address)
except socket.error as msg:
print('Failed to connect: %s' % msg)
raise
print('Connected')
def shutdown(self):
print('Shutting down')
self.sock.shutdown(socket.SHUT_RDWR)
self.sock.close()
def measure_temp():
bme_data = bme280_sensor.read_all()
obj = {}
obj['temp'] = round(bme_data[2], 2)
obj['humidity'] = round(bme_data[0], 2)
obj['pressure'] = round(bme_data[1], 2)
return json.dumps(obj)
def sendData(sock):
print('Sending data')
while True:
try:
data = 'data,' + measure_temp()
sock.sendall(data.encode())
except socket.error as msg:
print("Cannot send to server: %s" % msg)
break
time.sleep(5)
connection = Connection('192.168.1.100', 8888)
while True:
try:
connection.connect()
sendData(connection.sock)
connection.shutdown()
break
except socket.error as msg:
print('Connection failed, retrying in 3 seconds.')
time.sleep(3)
print('Done')
Node.js Server:
var net = require('net');
var port = 8888;
var server = net.createServer();
// socket io listens for clients on port 3000
var io = require('socket.io')(3000,{
pingInterval: 10000,
pingTimeout: 5000,
});
// server listens for python client on port 8888
server.listen(port);
console.log('Server started');
// store the last data recorded, so when a socket.io client connects, they can get the last reading instead of waiting for the next one
global.last;
server.on('connection', function(socket){
console.log('New server connection ' + socket.address().address);
// when the server recieves data, send it to the connected socket clients
socket.on('data', function(data){
// strip the first 5 characters from the input string, parse json from the result
var actual = generateJSON(data.toString().substring(5));
// store the dta
global.last = actual;
//send the data
io.sockets.emit('data', actual);
});
});
io.on('connection', function(socket){
console.log('New io connection ' + socket.id);
// if the server has data previously recorded, send it to the new client
if(global.last){
io.emit('data', global.last);
}
socket.on('disconnect', function(reason){
console.log('io disconnect: ' + reason);
});
});
function generateJSON(data){
var dataJSON = JSON.parse(data);
var obj = new Object();
obj.temperature = dataJSON.temp;
obj.humidity = dataJSON.humidity;
obj.pressure = dataJSON.pressure;
obj.datetime = new Date().toString();
return JSON.stringify(obj);
}
Website Javascript:
var socket;
var connected = false;
function connect(){
console.log('connecting...')
if(socket){
socket.destroy()
delete socket;
socket = null;
}
socket = io.connect("http://foobar.ddns:3000", {
forceNew: true,
reconnection: true,
reconnectionDelay: 3000,
reconnectionDelayMax: 5000,
reconnectionAttempts: Infinity
});
console.log(socket);
socket.on("data", function(data){
var obj = JSON.parse(data);
console.log(data);
$('#temperature-value').text(obj.temperature);
$('#humidity-value').text(obj.humidity);
$('#pressure-value').text(obj.pressure);
lastUpdate = new Date();
});
socket.on('connect_error', function(error){
console.log('connection error: ' + error);
});
socket.on('connect_timeout', function(){
console.log('connection timeout');
});
socket.on('reconnect', function(){
console.log('reconnect');
});
socket.on('reconnect_attempt', function(){
console.log('reconnect attempt');
});
socket.on('reconnect_failed', function(){
console.log('reconnect_failed');
});
socket.on('reconnect_error', function(){
console.log('reconnect_error');
});
socket.on('reconnecting', function(){
console.log('reconnecting');
});
socket.on('ping', function(){
console.log('ping');
});
socket.on('pong', function(ms){
console.log('pong ' + ms + "ms");
});
socket.on('connect', function(){
console.log('connected to server');
connected = true;
});
socket.on('disconnect', function(reason){
console.log('disconnected from server: ' + reason);
connected = false;
});
}
$(document).ready(function(){
connect();
});
I'm accessing the socket.io.js script with this in my index.html:
<script src="http://foobar.ddns:3000/socket.io/socket.io.js"></script>
This is functional but the disconnects are rather annoying, I'd rather the client stays connected. I have a feeling that my node.js server is not setup correctly, but I can't figure out what the issue is. If there's a better way to feed data from the python script > node.js server > web clients then please let me know.
Thanks
Share Improve this question asked Jun 29, 2018 at 14:10 Matt CleggMatt Clegg 3691 gold badge5 silver badges18 bronze badges 2- 1 I wonder if your raspberry Pi is going into some lower power mode. I turned off power management on mine. Also, is your Pi connected via ethernet or WiFi? There are separate power mgmt settings for WiFi. – jfriend00 Commented Jun 29, 2018 at 18:55
- @jfriend00 I thought the Pi doesn't have a low power mode, I'll have a look. They are both running via good quality cables and aren't getting any under-voltage warnings. They are both connected to my LAN via ethernet through a 1Gb switch (Netgear GS105). – Matt Clegg Commented Jun 30, 2018 at 14:33
1 Answer
Reset to default 1I've solved the issue! It had nothing to do with node.js or socket.io.
The issue was on the web page I have displaying the data, I had this method to update a span showing the seconds since the last update:
function updateLastUpdateTimer(){
var seconds = (new Date() - lastUpdate) / 1000;
$('#time-since-last-update').text(formatTime(seconds) + " ago");
$('#last-updated-time').text(lastUpdate);
setInterval(updateLastUpdateTimer, 1000);
}
The issue was setInterval
when it should have been setTimeout
. I realised that my web page was eating up RAM, which was causing the client socket to hang and not send any data to the server, which was causing the time out!
The setInterval
method runs a function every x milliseconds. DO NOT put it in the method you want to call! Call it once instead.
To anyone reading this who has the same issue with ping timeout and transport closed disconnects, check your client!
本文标签: javascriptSocketio client disconnects due to ping timeouttransport closedStack Overflow
版权声明:本文标题:javascript - Socket.io client disconnects due to ping timeouttransport closed - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745575046a2664277.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论