Trouble connecting Python socketio server to node js socketio client - python

I'm having a lot of difficulty with a very simple task. I'm attempting to set up a socket.io client in node js, which should then communicate with a local socket.io server setup in python (using the python bindings here. The issue I'm having is the server is detecting the client, but the client never seems to receive the 'connect' event. I suspect this is an issue with the way I've deployed the server asynchronously, but I'm really not sure. The code for each file is below:
server.py
import socketio
from aiohttp import web
HOST = '127.0.0.1'
PORT = 10001
# create a Socket.IO server
sio = socketio.AsyncServer(async_mode='aiohttp', logger=True, engineio_logger=True)
app = web.Application()
sio.attach(app)
#sio.on('connect')
def connect(sid, environ):
print('connect ', sid)
if __name__ == '__main__':
web.run_app(app, host=HOST, port=PORT)
client.js
const io = require('socket.io-client');
const HOST = '127.0.0.1';
const PORT = '10001';
const socket = io(`http://${HOST}:${PORT}`);
console.log('Socket instantiated!');
socket.on('connect', () => {
console.log(`socket connected: ${socket.connected}`);
});
The output I would expect is to see the server print out that the client has connected, and then for the client to print out that it has connected too. However, the client never seems to receive the 'connect' event, so never prints anything to the console.
Finally, an example of the server's output is:
Server initialized for aiohttp.
======== Running on http://127.0.0.1:10001 ========
(Press CTRL+C to quit)
1c17586e4c7e49b48abefea2fba460e6: Sending packet OPEN data {'sid': '1c17586e4c7e49b48abefea2fba460e6', 'upgrades': ['websocket'], 'pingTimeout': 60000, 'pingInterval': 25000}
connect 1c17586e4c7e49b48abefea2fba460e6
1c17586e4c7e49b48abefea2fba460e6: Sending packet MESSAGE data 0
While the client's output is annoyingly just
$ node mySocket.js
Socket instantiated!
and then it just hangs doing nothing.
I'm clearly misunderstanding something here, so thank you in advance!
Small update
I quickly tested using the python socketio client, and succesfully got an actual connection, so this should narrow it down to something I've done in the JS client.

Well, I ended up downgrading from socket.io-client 3.00 (did not see there was this major release 3 days ago) back to 2.3.1, and everything started working again! However, based on the lack of issues listed on Github, I'm guessing this is not a bug that is affecting everyone.

Related

Python: 404 Error when accessing page from localhost

I had a situation right now that is currently impeding my progress on my work.
I am trying to use Flask and Sockets together so that I can check if a certain user is connected or not before I can show a video feed on the web browser.
Here is my code below.
from flask import Flask, render_template, Response, jsonify, request
from flask_socketio import SocketIO
from camera import VideoCamera, SocketConnections
import socket
import pickle
import struct
import new_client as NC #this is a client module
app = Flask(__name__)
video_camera = None
global_frame = None
urlfor_container = ""
HOST = ''
PORT = 5000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('Socket created')
s.bind((HOST, PORT))
print('Socket bind complete')
s.listen(10)
print('Socket now listening')
c = SocketConnections('127.0.0.1',5000)
c.Establish_Connection()
conn, addr = s.accept()
print('connected workstation ', addr)
data = b'' ### CHANGED
payload_size = struct.calcsize("L") ### CHANGED
# check if the connection was accepted
app.run(host='',threaded=True)
When I run this code, everything seems to be fine.
====== RESTART: C:\CENTRALIZED_SYSTEM_FILES\OpenCV Demozz\new_cam_serv.py ======
Socket created
Socket bind complete
Socket now listening
test message should print if code was accessed
connected
connected workstation ('127.0.0.1', 59283)
* Serving Flask app "new_cam_serv" (lazy loading)
* Environment: production
[31m WARNING: This is a development server. Do not use it in a production deployment.[0m
[2m Use a production WSGI server instead.[0m
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
However when I tried to access the webpage from localhost (localhost:5000/127.0.0.1:5000), I'm receiving a " 404 Page Not Found" error. I already have a templates folder along with the index.html inside the same folder where the main module is located but every time I run this code, I still receive the 404 message.
Also, I've tried using different variations for the IP address but no luck, still 404.
Any help from you guys will be greatly appreciated. Thank you.
EDIT: I've tried create an if name=="main" statement at the bottom and then inserted this code snippet inside the clause. Then I noticed that the flask server ran successfully and I was able to browse the page again, but here is the issue. after I interrupted the execution, then that is the only time my code for the socket connection got executed.
So my question now is... is it even possible for the socket and Flask to be used at the same time?
Thank you again.
I just want to provide an update that I have found a solution to this. It is indeed possible to use both socket and Flask at the same time.
I found out that the app.run() requires a valid IP address for it to work when used with socket. The IP address from the socket and the IP address from Flask need to be the same IP address or else it won't work. I found that out when I tried to debug my script and noticed that the socket and Flask on my script are referring to different IP addresses.
So, I changed:
app.run(host='',threaded=True)
to this:
app.run(host='127.0.0.1',threaded=True)
I've tried this with other IP addresses and it is working just fine.
Thank you again, everyone.

Socket.io in flask: Data from external source

I have a web application and need to continuously display the actions going on in the backend on the browser. I have been trying to use socket.io in Flask. But I need to get the data to be displayed from other Python modules in my project. So, I tried to make a socket connection between Flask and the external module from which I will be getting data to be displayed on the browser(without any delay).
#socketio.on('my event')
def server(message):
s = socket.socket()
print "Socket successfully created"
port = 12345
s.bind(('', port))
print "socket binded to %s" %(port)
s.listen(5)
print "socket is listening"
while True:
c, addr = s.accept()
print 'Got connection from', addr
print c.recv(1024)
emit('my response', {'data': c.recv(1024)})
c.close()
print c.recv(1024) is printing data on the console. But the same data is not getting reflected on the browser. It's throwing this error -
error: [Errno 98] Address already in use
This means it's failing at emit after print c.recv(1024). What could be going wrong?
My first doubt is if this kind of connection is allowed. I mean, can we have a socket connection created inside socket.io in Flask?
Else, what is the best solution to display the backend actions on the browser continuously using Flask? I also have the web application with Django. Any solution for my use case with either Flask or Django will be appreciated (preferably Django).
Using the answer given by Miguel, I could find an appropriate solution. In the external script, we need to create a SocketIO object as follows:
socketio = SocketIO(message_queue='redis://')
Then I can use emit to send the data to be displayed on the front end.
def fn():
socketio.emit('my response', {'data': 'ur data goes here'})
fn()
And on the frontend,
var socket = io.connect('http://' + document.domain + ':' + location.port);
socket.on('connect', function() {
socket.on('my response', function(msg) {
$('#log').append('<p>Received: ' + msg.data + '</p>');
document.getElementById('<div_id>').innerHTML += msg.data + "<br>";
});
});
Finally, on the Flask server side, we need to create the SocketIO object as follows:
socketio = SocketIO(app, message_queue='redis://')
Then run Flask with socketio.run(app,host='<ip>',port=<port>)
The problem is that each time a client sends the event named my event to your server, you will try to start a new socket server on port 12345. Obviously this is only going to work the first time.
Have you seen the Emitting from an External Process section in the documentation?
The idea is that you can emit events to clients from any auxiliary process, which is exactly what you need. The solution involves installing a message queue (Redis, RabbitMQ), to which the Flask-SocketIO server and the external processes that need to have emit powers connect to.

Do I need tcp:// in the MQTT broker address?

I have searched both the web and stockexchange for an explanation of this strange behavior I experience when connecting to MQTT. But I couldn't find any similar case and I would like to understand where the issue comes from.
So, I have set up a Mosquitto MQTT broker on my Raspberry Pi to listen on port 1883. I have also set up port forwarding on my router, so I can reach the Pi from outside my home network (though I can reproduce the behavior below with a public server like broker.hivemq.com as well). When I execute the following Node.js script, I can connect to the broker and subscribe and publish messages, it works perfectly:
const mqtt = require('mqtt')
const client = mqtt.connect('tcp://my.address.net:1883')
client.on('connect', () => {
console.log('Connected!')
client.subscribe("chat")
})
var readline = require('readline');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false
});
rl.on('line', function(line){
client.publish('chat',line)
})
client.on('message', (topic, message) => {
console.log('>> '+message)
})
However, when I leave out the tcp:// protocol and have
const client = mqtt.connect('my.address.net:1883')
as the host address I don't get a connection, but also no error message. The program just hangs until I terminate it. I don't understand that. Isn't MQTT using TCP by default?
Does that have to do with my client or with my broker? Could it have something to do with my system (OSX)?
Maybe this has nothing to do with it, but a similar behavior I get when I use the Paho MQTT package in Python, and this is actually the more important case for me, because here I don't get it to run at all. This is my code:
import paho.mqtt.client as paho
def on_connect(client, userdata, flags, rc):
print("connected")
client.disconnect()
def on_disconnect(client, userdata, rc):
print("disconnected")
client = paho.Client()
client.on_connect = on_connect
client.on_disconnect = on_disconnect
client.connect("my.address.net", 1883)
Using this version without protocol, I don't get any response. The program runs for a second and then terminates. If I use the protocol
client.connect("tcp://my.address.net", 1883)
I get the error
socket.gaierror: [Errno 8] nodename nor servname provided, or not known
I don't know what I am missing.
Can someone explain the difference of stating the tcp:// protocol in the address vs. leaving it out?
This is two question.
For the python part, the python client expects host and port separately as its connection arguments. It is not a URI. Hence no TCP//.
The python program does exactly what you ask - connect, then exit. You'll have to add more code beneath the connect call if you want it to do anything else. What that code is depends on what you want to do, but loop_forever() is a good start.
The other client expects a URI. I believe it uses TCP/SSL to distinguish between plain and encrypted connections.
The 2 libraries are requiring different things.
The NodeJS library is asking for a URI which includes
a schema ("tcp://")
a hostname/IP address ("local host")
a port number (":1883")
The host and port can easily be parsed from this.
Where as the Python library is explicitly asking for 2 separate things
the hostname
the port
These are taken as separate variables.
This just down to different authors choosing different approaches to gather information.

Python Pika and RabbitMQ Connecting to Publish

Trying to send data into a RabbitMQ queue using Python.
I haven't configured the server but it is running for other processes. I have a working login and can access the web output without problem.
The example code RabbitMQ gives for python uses Pika:
#!/usr/bin/env python
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='xxx.xxx.xxx.xxx:xxxxx'))
channel = connection.channel()
channel.queue_declare(queue='Test')
channel.basic_publish(exchange='',
routing_key='hello',
body='Hello World!')
print(" [x] Sent 'Hello World!'")
connection.close()
This runs and kicks me off with:
pika.exceptions.ConnectionClosed
Not a lot to go on but safe assumption is a login issue because the example code doesn't have any login info.
So I added it.
import pika
import sys
try:
credentials = pika.PlainCredentials('username', 'password')
connection = pika.BlockingConnection(pika.ConnectionParameters('xxx.xxx.xxx.xxx',
xxxxx,
'virtualhostnamehere',
credentials,))
channel = connection.channel()
channel.queue_declare(queue='Test')
channel.basic_publish(exchange='amq.direct',
body='Hello World!')
print(" [x] Sent 'Hello World!'")
except:
e = sys.exc_info()[0]
print e
It seems to hang around for a good few minutes before giving me:
<class 'pika.exceptions.IncompatibleProtocolError'>
The server is running other services fine but I can't seem to pinpoint what I've done wrong.
The login is correct. The vhost name is correct. The host is correct. the exchange name is correct.
Would appreciate a point in the right direction.
Update:
I've tried using URLParameters as well with the same results.
parameters = pika.URLParameters('amqp://username:password#xxx.xxx.xxx.xxx:xxxxx/notmyvhostname')
connection = pika.BlockingConnection(parameters)
But I guess the port doesn't change anything. It's port 15672 and the
login is the same as I used to get on the browser output.
Use port 5672 - or whichever default port you have setup for AMQP listener. Port 15672 is for web UI access, which is done over HTTP, hence the incompatible protocol error

Python : How do server come to know of network failure at the client side?

I am developing a chat based application in Python using twisted module.
After a period of establishing the connection, let us assume, that the network connection fails at the client side.
How do I make sure that the server is notified about the network failure ?
Here is the code snippet( Server program) :
def main():
"""This runs the protocol on port 8000"""
factory = protocol.ServerFactory()
factory.protocol = Echo
PortNo = 8000
reactor.listenTCP(PortNo,factory)
reactor.run()
# this only runs if the module was *not* imported
if __name__ == '__main__':
main()
Thanks
This http://twistedmatrix.com/documents/13.0.0/api/twisted.internet.interfaces.IProtocol.html#connectionLost
But to be realy sure, you'd have to implement PING/PONG in the application. See https://www.rfc-editor.org/rfc/rfc2812#section-3.7.2
You have to (1) use a read timeout and (2) make sure you react appropriately to all error conditions when reading from or writing to the socket.

Categories

Resources