0

My overall goal is to generate a stream of random numbers in a JavaScript file (which is run using node) and send them to a python script in asynchronous time intervals. Once the numbers are in python, the script will determine if the numbers are even, or not. If they are, the numbers are sent back to the JavaScript file. My main focus is to get the communication between JavaScript and Python.

Once I begin the JavaScript file and python server, they will continue running until I stop them.

Currently, I have been working off the tutorial located here (https://tutorialedge.net/python/python-socket-io-tutorial/). The tutorial uses socket io for JS and aiohttp for python.

I manipulated the html code into a JS code (index.js), which is below:

// index.js    
var socket = require('socket.io-client')('http://localhost:8080');
socket.on('connect', function(){});

function generateNumber() {
   let n = Math.floor(Math.random() * 50);
   let json = {
       'number': n
   }
   console.log(json);
   return json;
}

(function loop() {
    var rand = Math.round(Math.random() * (3000 - 500)) + 500;
    setTimeout(function() {
            generateNumber();
            loop();  
    }, rand);
}());

function sendMsg() {
  socket.emit("message", generateNumber());
}

socket.on("message", function(data) {
console.log(data);
});

I created a function (generateNumber) to produce random numbers outputted in JSON format. I am using JSON because I believe it will allow for data to be easily converted into lists and integers when the numbers reach the python script. The loop function allows the numbers to be created at random intervals continuously and was taken from here: Randomize setInterval ( How to rewrite same random after random interval)

The python server (server.py) shown below, was taken from the tutorial (https://tutorialedge.net/python/python-socket-io-tutorial/):

# server.py
from aiohttp import web
import socketio

# creates a new Async Socket IO Server
sio = socketio.AsyncServer()
# Creates a new Aiohttp Web Application
app = web.Application()
# Binds our Socket.IO server to our Web App
# instance
sio.attach(app)

# we can define aiohttp endpoints just as we normally
# would with no change
async def index(request):
    with open('index.html') as f:
        return web.Response(text=f.read(), content_type='text/html')

# If we wanted to create a new websocket endpoint,
# use this decorator, passing in the name of the
# event we wish to listen out for
@sio.on('message')
async def print_message(sid, message):
    # When we receive a new event of type
    # 'message' through a socket.io connection
    # we print the socket ID and the message
    print("Socket ID: " , sid)
    print(message)

# We bind our aiohttp endpoint to our app
# router
app.router.add_get('/', index)

# We kick off our server
if __name__ == '__main__':
    web.run_app(app)

As of now, when I run node index.js, random numbers are continuously generated at random intervals and the output can be seen in the terminal. But I am not getting a response on the server side.

I believe the problem is related to the following 2 issues:

First, my current JS code (index.js) was originally a html script that sent a message with a button click hosted on “http://localhost:8080.” I adjusted the script to be a JS script, as well as adding additional functions. So there may be an issue in the following lines of index.js where I setup socket io:

var socket = require('socket.io-client')('http://localhost:8080');
socket.on('connect', function(){});

For clarity, here is the original html code (index.html) that index.js is based off:

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <button onClick="sendMsg()">Hit Me</button>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script>
    <script>
      const socket = io("http://localhost:8080");

      function sendMsg() {
        socket.emit("message", "HELLO WORLD");
      }
    </script>
  </body>
</html>

I also asked a previous question related to the html to JS conversion (Syntax error when trying to convert HTML file to JavaScript containing socket io, SyntaxError: Unexpected token <)

Second, because the tutorial originally used a html file rather than JS, I believe the python script (server.py) is still waiting on output from a html script, so I think these lines in server.py need to be changed:

async def index(request):
    with open('index.html') as f:
        return web.Response(text=f.read(), content_type='text/html')

But I am unsure how to make the proper changes, I am having issues finding references to my question on the aiohttp site (https://aiohttp.readthedocs.io/en/stable/), or I may be unsure as to what I am looking for.

Both server.py and index.js currently run without errors, but they are not communicating.

Overall, the JS file (index.js) will be sending data to a python server (server.py) using socket io, and the python server, using aiohttp, will be sending back the analyzed data to the same JS script. This will happen continuously until one of the scripts is stopped manually.

If any clarification is needed on anything, please feel free to ask.

W. Churchill
  • 346
  • 1
  • 7
  • 28

1 Answers1

1

I believe, in JS part, you should call sendMsg() somewhere in order to emit a message.

Updated

const io = require('socket.io-client');

const socket = io('http://localhost:8080');

socket.on('message', data => {
  console.log('Got from server: ');
  console.log(data);
});

function generateNumber() {
  const n = Math.floor(Math.random() * 50);
  return { number: n };
}

function sendMsg() {
  const json = generateNumber();
  console.log('Sending to server:');
  console.log(json);

  socket.emit('message', json);
}

function loop() {
  const rand = Math.round(Math.random() * (3000 - 500)) + 500;
  console.log(`Setting timeout ${rand}ms`);
  setTimeout(() => {
    sendMsg();
    loop();
  }, rand);
}

socket.on('connect', () => {
  console.log('Connected to server');
  loop();
});

I was using node on both sides. The server side just sends back every received message. The logs look like this:

Connected to server
Setting timeout 1685ms
Sending to server:
{ number: 21 }
Setting timeout 1428ms
Got from server: 
{ number: 21 }
Sending to server:
{ number: 40 }
Setting timeout 2955ms
Got from server: 
{ number: 40 }
xx NF xx
  • 26
  • 4
  • Your suggestion worked. But there are some issues, the numbers are not being sent consistently. Sometimes only a few numbers will go to the python server, other times maybe one number goes through. However, there are times where maybe the first 10 numbers will not go through and then the script begins to work as it should. I continually need restart the server and JS script to try to get them working properly. Do you think this may be something on the JS side? – W. Churchill Apr 23 '19 at 07:47
  • @W.Churchill Please check updated version. I've added more logs and **.on('connect')** listener to prevent any actions before socket connects to the server – xx NF xx Apr 23 '19 at 14:32
  • Thanks for the updated version, I have been working with the code and have some more questions. When you say you are using node on both sides does that mean you are using a JavaScript server? I would like to use my Python server, but I am having some issues running the current updated version of the code, when running it (using my python servery, server.py) I do not receive the "Got from server:" message on the JS side, but I see numbers being received on the Python server side. – W. Churchill May 02 '19 at 05:12
  • Some things I have noticed: If the connection is not established, the JS side will output the "Connected to server" message every minute, and maybe 1 or 2 numbers will go through and the process repeats every minute until a consistent connection is established, however, sometimes no connection will be established. – W. Churchill May 02 '19 at 05:14
  • So both the JS script and python server need to be restarted. When starting the JS script after the python server is running, it will take about 1 to 3 minutes for the connection to establish and numbers be sent consistently, if not, I have to continually restart both scripts until the connection is established. But when a connection is established it will run continually without interruption (I have been currently running one connection for more than 3 days). So do you believe this is now an issue on the Python side and something to do with server.py? – W. Churchill May 02 '19 at 05:14
  • I got everything working and can receive a "Got from server:" message in JS console, but the only issue left is that the connection between the client and server is not happening right when the scripts are run, it takes a few minutes, which I describe in a previous comment. – W. Churchill Jun 11 '19 at 04:11