title: Socket.io client disconnects due to ping timeout / transport closed
body: <p><strong>Here's my setup:</strong></p>
  
  <p>Raspberry Pi 2 (192.168.1.101):</p>
  
  <ul>
  <li>Sensor recording temperature, pressure and humidity.</li>
  <li>Python3 script connected to a Raspberry Pi 3, reading sensor data and sending to Pi 3, in JSON format, every 5 seconds.</li>
  </ul>
  
  <p>Raspberry Pi 3 (192.168.1.100):</p>
  
  <ul>
  <li>Node.js server listening for python client on port 8888.</li>
  <li>Socket.io listening for web clients on port 3000 (port 3000 and 80 have been opened on my router).</li>
  <li>Web server (on port 80) with a website displaying sensor data.</li>
  <li>JavaScript connecting to node server, using socket.io, via foobar.ddns.net:3000.</li>
  </ul>
  
  <p>Misc:  </p>
  
  <ul>
  <li>I'm using noip.com 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.net.</li>
  </ul>
  
  <p>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.</p>
  
  <p>My issue is that the web client disconnects after 1 round of ping/pong between the client and node server.</p>
  
  <p>Here's the chrome console log when connected to the server and receiving data: 
  <a href="https://i.stack.imgur.com/ZTpAg.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/ZTpAg.png" alt="chrome console log"></a></p>
  
  <p>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.</p>
  
  <p>And here's the node.js log:<br>
  <a href="https://i.stack.imgur.com/ZdfWU.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/ZdfWU.png" alt="node.js server log"></a></p>
  
  <p>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.</p>
  
  <p>Changing the pingTimeout and pingInterval values just delays the disconnect.</p>
  
  <p>Here's my code:</p>
  
  <p>Python Client:</p>
  
  <pre><code>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')
  </code></pre>
  
  <p>Node.js Server:</p>
  
  <pre><code>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);
  }
  </code></pre>
  
  <p>Website Javascript:</p>
  
  <pre><code>var socket;
  var connected = false;
  
  function connect(){
      console.log('connecting...')
  
      if(socket){
          socket.destroy()
          delete socket;
          socket = null;
      }
  
      socket = io.connect("http://foobar.ddns.net: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();
  });
  </code></pre>
  
  <p>I'm accessing the socket.io.js script with this in my index.html:<br>
  <code>&lt;script src="http://foobar.ddns.net:3000/socket.io/socket.io.js"&gt;&lt;/script&gt;</code></p>
  
  <p>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.</p>
  
  <p>Thanks</p>