Flask SocketIO web app refuses to accept connections from python file - python

I am trying to send some data to a Flask app using web sockets. Never done something like this so I might be doing something very wrong but so far I haven't been able to accept a single connection.
For the moment I have 2 python files, server.py and client.py.
server.py starts the flask server and the web socket, then client.py should be able to connect to it, send a message, which is printed out to the server console, then the server should echo that message back where it will be received by the client and print to the client console.
However right now I am getting a Handshake status 400 BAD REQUEST error when the client tries to connect.
Here is the code I'm using:
server.py :
from flask import Flask, render_template
from flask_socketio import SocketIO
app = Flask(__name__)
app.config['SECRET_KEY'] = 'hi'
socketio = SocketIO(app)
#app.route('/')
def sessions():
return "Hello World"
#socketio.on('message')
def handle_my_custom_event(mes):
print('received my event: ' + str(mes))
socketio.emit('my response', mes)
if __name__ == '__main__':
socketio.run(app, debug=True)
client.py :
import websocket
websocket.enableTrace(True)
ws = websocket.create_connection("ws://localhost:5000")
print("Sending 'Hello, World'...")
ws.send("Hello, World")
print("Sent")
print("Receiving...")
result = ws.recv()
print("Received '%s'" % result)
ws.close()
I think there is something wrong with the server.py file but, i've been flowing the Flask-SocketIO docs and its pretty much identical to their getting started example. But then again, I also don't know enough about this so i have no real idea where the problem lies.
Any help is appreciated thank you!

The problem is with your client. Websocket and socket.io aren't the same, socket.io protocol can use websockets under the hood but you cannot just connect with websocket client to socket.io server.
What you want to use is socket.io client.
And if you don't mind I highly encuorage you to use FastAPI instead of flask. It's much simpler, faster and have much better documentation. Here you can find complete and working example of websocket server and client with FastAPI

Related

How can i invoke a flask endpoint directly from code without using requests

Hey everyone I was tasked a few days ago to create an API style application that listens over a TCP socket for some commands then return some responses mainly success/failures (i know it's dumb but it's the client request) since I have some validation/database stuff I thought of flask directly but I am still stuck on how I am going to invoke the specific endpoints in code directly. here is a small snippet on how I am imagining things would be
from flask import Flask
import threading
data = 'foo'
app = Flask(__name__)
#app.route("/SomeCommand")
def SomeCommand():
return { 'Some' : 'Response'}
def flaskThread():
app.run()
def TcpListenner():
# logic that listens over tcp socket then invoks the flask app
# I was thinking about calling app.something() from here
pass
if __name__ == "__main__":
flaskApp = threading.Thread(target=flaskThread)
flaskApp.start()
listenner = threading.Thread(target=TcpListenner)
listenner.start()
any help/ideas would be much appreciated, thank you
You can use flask_socketio with which the flask app and socket i.e. tcp listener both start together...
Based on what I've understood, you can do something like this:
That the client will first make a connection to the flask socket.
Then, to send a command to the flask app, the client will send a message to the flask socket with the command in its message.
The flask socket will be listening for messages. So when it receives a message for the specific command, then it emits a response based on that command to the socket which will then be received by the client.
Below is an example code for the flask socket app:
import eventlet
eventlet.monkey_patch()
from flask import Flask
from flask_socketio import SocketIO, send, emit
app = Flask(__name__)
socketio = SocketIO(app, cors_allowed_origins="*", logger=True, engineio_logger=True)
# other flask APIs can come here and can be called by the client...
def someCommandOneResponse(): # function that sends response to client when flask socket gets command 1
commandOneResponse = 'Success'
socketio.emit('message', commandOneResponse)
def someCommandTwoResponse(): # function that sends response to client when flask socket gets command 2
commandTwoResponse = 'Failure'
socketio.emit('message', commandTwoResponse)
#socketio.on('message') # when any command is received on the socket from the client
def handleMessage(cmd):
print('\nCommand Received: ' + cmd + '\n')
if( cmd == 'SomeCommand1' ): # if the client has sent a message for command 1
print('Got Some Command 1')
someCommandOneResponse()
elif( cmd == 'SomeCommand2' ): # if the client has sent a message for command 2
print('Got Some Command 2')
someCommandTwoResponse
send(cmd, broadcast=True)
if __name__ == '__main__':
socketio.run(app, port=3000) # starts the flask socket (tcp listener) as well as the flask app

python flask-socketio server receives message but doesn't trigger event

I'm using flask and socketio to build a server-client comms system. A simplified version of it is below, which replicates the issue I'm having. Basically, the client can connect to the server and can send messages and receive acknowledgements back, however the messages don't seem to trigger the handler functions on the server. In the example below, I'm expecting the sever to have 'RECEIVED: {} {}' in the logs, as it should call the handle_message method, but there's nothing, despite it specifically saying it's received the 'test' event. I've tried a few different iterations and versions to try to work out what's happening, but I have no idea what's causing the issue. Any help you can provide would be greatly appreciated! Thanks!
test_simple.py:
import sys
import time
from flask import Flask
from flask_socketio import SocketIO
import socketio as sio
from socketio import Client
app = Flask(__name__)
socket = SocketIO(app, engineio_logger=True, logger=True)
#socket.on('test') ## try decorator as .on_event isn't working
def handle_message(*args, **kwargs):
print('RECEIVED: ', args, kwargs)
app.logger.error(f'RECEIVED: {args}, {kwargs}')
socket.emit('reply', 'hello client')
return 'hello client'
def message_callback(*args, **kwargs):
print('CALLBACK: ', args, kwargs)
def startup_server():
#app = Flask(__name__)
#socket = SocketIO(app, cors_allowed_origins="*",
# engineio_logger=True, logger=True)
#socket.on_event('test', handle_message) # this doesn't work either
#socket.on_event('message', handle_message)
socket.run(app, host='127.0.0.1', port=8001, debug=True,
use_reloader=False)
def startup_client():
socket = Client(logger=True, engineio_logger=True)
socket.connect('http://127.0.0.1:8001')
socket.on('reply', message_callback)
socket.emit('test', data='hello world', callback=message_callback)
time.sleep(5)
#socket.send(data='hello message', callback=message_callback)
#time.sleep(5)
socket.disconnect()
if __name__ == '__main__':
if sys.argv[1] == 'predictor':
startup_client()
else:
startup_server()
Server logs:
python3 test_simple.py aggregator
Server initialized for gevent.
54Pavf_I3leodKsoAAAA: Sending packet OPEN data {'sid': '54Pavf_I3leodKsoAAAA', 'upgrades': ['websocket'], 'pingTimeout': 20000, 'pingInterval': 25000}
54Pavf_I3leodKsoAAAA: Received request to upgrade to websocket
54Pavf_I3leodKsoAAAA: Upgrade to websocket successful
54Pavf_I3leodKsoAAAA: Received packet MESSAGE data 0
54Pavf_I3leodKsoAAAA: Sending packet MESSAGE data 0{"sid":"xH33UEQVeWzMXauFAAAB"}
54Pavf_I3leodKsoAAAA: Received packet MESSAGE data 21["test","hello world"]
received event "test" from xH33UEQVeWzMXauFAAAB [/]
### << expecting 'RECEIVED: {} {}' here >> ###
54Pavf_I3leodKsoAAAA: Sending packet MESSAGE data 31["",400]
Client logs:
python3 test_simple.py predictor
Server initialized for gevent.
Attempting polling connection to http://127.0.0.1:8001/socket.io/?transport=polling&EIO=4
Polling connection accepted with {'sid': '54Pavf_I3leodKsoAAAA', 'upgrades': ['websocket'], 'pingTimeout': 20000, 'pingInterval': 25000}
Engine.IO connection established
Sending packet MESSAGE data 0
Attempting WebSocket upgrade to ws://127.0.0.1:8001/socket.io/?transport=websocket&EIO=4
WebSocket upgrade was successful
Received packet NOOP data
Received packet MESSAGE data 0{"sid":"xH33UEQVeWzMXauFAAAB"}
Namespace / is connected
Emitting event "test" [/]
Sending packet MESSAGE data 21["test","hello world"]
Received packet MESSAGE data 31["",400]
Received ack [/]
CALLBACK: ('', 400) {} ## << expected to receive 'hello client' >> ##
## << no 'reply' event trigger >> ##
Solved it - thanks for your help Miguel! The issue was the package versions; I was using Flask 1.1.2 and Flask-SocketIO 4.3.1, which I hadn't realised was a separate package and I'd only tried updating Flask (and socketio-client, but I was already using the most update-to-date version of that). Once I'd updated to Flask 2.0.1 and Flask-SocketIO 5.1.0 as well, it suddenly started working as I'd expected it to. Now I feel dumb, haha

How to connect/listen to nsqd from a webserver

So I have a simple flask server and wanted to listen to nsqd,(My nsqd and nsqlookupd dockers are running fine.) I'm using gnsq from python as a tool to achieve that
server.py:
from flask import Flask
import gnsq
consumer = gnsq.Consumer('test_topic', 'test_channel', '0.0.0.0:4161')
#consumer.on_message.connect
def handler(consumer, message):
print ('got message:', message.body)
consumer.start()
app = Flask(__name__)
#app.route("/")
def hello():
return "Flasky"
and when I run the server all I get is
[0.0.0.0:4161] connection failed (NSQSocketError(57, 'Socket is not connected'))
I tried changing ports as well but still persist.

rpyc server call client method

I am currently using rpyc for constructing a server and multiple clients that will connect to it. I have data in the clients that I would like to push to the server for further processing, and I would like to do it with the server calling a client method whenever the client connects to the server. From their tutorial, it says that clients can expose their service to the server, but I am getting errors.
Code for my server:
import rpyc
class TestService(rpyc.Service):
def on_connect(self, conn):
conn.root.example()
if __name__ == "__main__":
from rpyc.utils.server import ThreadedServer
t = ThreadedServer(TestService, port=18861, auto_register=True)
t.start()
Code for my client:
import rpyc
class ClientService(rpyc.Service):
def exposed_example(self):
print "example"
if __name__ == "__main__":
try:
rpyc.discover("test")
c = rpyc.connect_by_service("test", service=ClientService)
c.close()
except:
print "could not find server"
The client is able to connect to the server, but there will be an exception in thread and an error: raise EOFError("stream has been closed"). It is complaining about the line conn.root.example() and I don't know what the correct syntax would be, and the tutorial did not specify at all.
Any help will be much appreciated!

iOS - How to connect to flask server using flask-socketIO with out namespace?

I'm building an iOS app which receive data from socket. I'm quite new to things about socket.
I use flask framework to build my server. To implement the long poll, I find the flask-socketIO package. However I haven't found some useful tutorial.
I use CocoaAsyncSocket to conncet and send data to the server and it works fine when I test a naive python socket. Code:
from socket import *
from time import ctime
serverClient = socket(AF_INET, SOCK_STREAM)
HOST='127.0.0.1'
PORT=8808
BUFSIZ=1024
ADDR=(HOST, PORT)
serverClient.bind(ADDR)
serverClient.listen(5)
while True:
print('waiting for input')
clientSocket, addr = serverClient.accept()
print('connect from ', addr)
while True:
try:
data= clientSocket.recv(BUFSIZ)
except:
print(e)
clientSocket.close()
break
if not data:
break
s='Hi,you send me :[%s] %s' %(ctime(), data.decode('utf8'))
clientSocket.send(s.encode('utf8'))
print([ctime()], ':', data.decode('utf8'))
clientSocket.close()
serverClient.close()
However, I don't know how to put it together with my flask server. This is also why I try flask-socketIO.
Under the instruction of the document, I implement
#socketio.on('connect', namespace='/test')
def test_connect():
emit('my response', {'data': 'Connected'})
in my views.py.
Can I do without specifying the namespace? But without specifying a namespace, the default one is '/', will it conflict with my home directory?
Socket.IO is a specialized protocol, not a plain networking library. If you are going to use Socket.IO on your server, then you need to use a Socket.IO client on your iOS device, such as this one: https://github.com/socketio/socket.io-client-swift.

Categories