I would like to run two servers in parallel when my application starts, one for HTTP requests, one for websockets (using python-sockio). I already have a python back-end which starts an HTTP-based server with Flask. However, every time I start the first server, it seems like it is blocking the thread which in turn, causes my second server not to initialize at all. Since I'm using Flask, is there a Flask-way to do this?
you can try to run the two servers on 2 different ports like so
flask run --host 0.0.0.0 --port 5000
flask run --host 0.0.0.0 --port 5001
If I did a terrible job explaining try and look at this thread Python - How to run multiple flask apps from same client machine
Sounds like an XY problem. Your app can serve both websockets and HTTP. Here's a code example taken from Miguel Grinberg's Flask-Socketio example:
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
#app.route('/')
def index():
return render_template('index.html')
#socketio.on('my event')
def test_message(message):
emit('my response', {'data': 'got it!'})
if __name__ == '__main__':
socketio.run(app)
Related
Situation:
I deploy my flask server in the AWS EC2 ubuntu and running. And react.js running on my local machine try to test is remote server setup correctly and works, contains Restful API and WebSocket.
Question:
Everything works fine on the local machine which python and react both running on the local machine. When l make flask running on the AWS, the Restful API works fine, but WebSocket is not working, there is no connect refused error, switch protocol is 101 and in the inspector network section is 200 status. Just remote server cannot receiving data. I am not sure what was happended at this time and how to fix that, anyone has the same experience?
this one is my client
const endPoint = "http://3.237.172.105:5000/friends";
const socket = io.connect(endPoint);
const addFriends=(friend)=>{
socket.emit("Addedfriend",{username:name , friendName:friendName});
}
this one is my flask start file: call python3 app.py to run
from logging import debug
from flask import Flask
from flask_socketio import SocketIO
from flask_cors import CORS
from Controller.logReg import logReg
from Controller.profile import profile
from Controller.ticket import ticket
from Controller.personal import personal
import logging
#log = logging.getLogger('werkzeug')
#log.setLevel(logging.ERROR)
app = Flask(__name__)
socketio = SocketIO(app, cors_allowed_origins="*")
app.register_blueprint(logReg)
app.register_blueprint(profile)
app.register_blueprint(ticket)
app.register_blueprint(personal)
print("socket started ... ...")
CORS(app)
if __name__ == '__main__':
print("socket opened")
socketio.run(app, host='0.0.0.0', port=5000)
this is my socket file: print data is not print anything and I am not sure why
#socketio.on('Addedfriend', namespace='/friends')
def add_friend(data, t):
print("this is from addFriend" + str(data))
# print("friend SID: "+str(request.sid))
user = data['username']
friend = data['friendName']
user_friends = FriendsDB.find_one({"username": user})['friends']
if friend in user_friends:
emit("Addedfriend", {"result": "already added", "friendPhoto":"", "friendStatus": False})
return
if FriendsDB.find_one({"username": friend}) is None:
emit("Addedfriend", {"result": "Not Exist", "friendPhoto": "", "friendStatus": False})
return
this is the network screenshot
this is AWS IP address
this is AWS inbound rule
I am trying to host a simple websocket using Flask SocketIO with nothing but client disconnect and client connect command.
But I'm not sure what is not working properly.
Here is my server code
server.py
from flask import Flask
from flask_socketio import SocketIO
app = Flask(__name__)
app.config['SECRET_KEY'] = 'very-secret'
socketio = SocketIO(app)
#socketio.on('connect')
def client_connect():
print("HII")
emit({'data': 'Hii'})
#socketio.on('disconnect')
def client_disconnect():
print('client disconnected')
#socketio.on('message')
def message(msg):
print(msg)
emit({'data':'lol'})
if __name__ == '__main__':
app.debug = True
socketio.run(app, port=2345)
When I start the server it says
Restarting with stat
Debugger is active!
Debugger PIN: 774-937-680
But doesn't say "Running on *********" message.
I am unable to find out what is the problem.
For client, I'm using some Chrome websocket client. The client connects but instantly disconnects.
I tried with Firefox websocket client too. Same thing with that.
Thank you in advance.
the syntax for emit is
emit(event,*args, **kwargs)
you haven't mentioned the event on which you want to emit the data. Try this might work
I am primarily a Javascript developer but I am trying to replicate a server I wrote in Node.js in Python. The server uses Socket.io to communicate with clients and I am having some trouble replicating this specific behaviour in Python:
io.on('connection', function(socket){
socket.on('disconnect', function(){ });
});
I would like to handle each client's events and messages separately from one another. Any way I could do this in Python? I am using the package flask_socketio to wrap the sockets. Cheers.
As far as I can see you just want connection and disconnection handlers?
You can do that as follows in Python:
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
app = Flask(__name__)
socketio = SocketIO(app)
#socketio.on('connect')
def connect():
# your connection logic here
#socketio.on('disconnect')
def disconnect():
# your disconnection logic here
if __name__ == '__main__':
socketio.run(app)
I've created a single socket endpoint on the server side that looks like this:
Server.py
from client import sockio_client
from flask_socketio import SocketIO
from flask import Flask
app = Flask(__name__)
socketio = SocketIO(app)
#socketio.on('status_update')
def status_update(data):
print('got something: ',data)
#app.before_first_request
def start_ws_client():
# now that server is started, connect client
sockio_client.connect('http://localhost:5000')
if __name__ == "__main__":
socketio.run(app,debug=True)
And the corresponding client:
Client.py
import socketio
from threading import Thread
sockio_client = socketio.Client()
# wait to connect until server actually started
# bunch of code
def updater():
while True:
sockio_client.emit('status_update', 42)
time.sleep(10)
t = Thread(target=updater)
t.start()
I've got a single background thread running outside of the server and I would like to update clients with the data it periodically emits. I'm sure there is more than one way to do this, but the two options I came up with were to either (i) pass a reference to the socketio object in server.py above to the update function in client by encapsulating the update function in an object or closure which has a reference to the socketio object, or (ii) just use a websocket client from the background job to communicate to the server. Option one just felt funny so I went with (ii), which feels... okish
Now obviously the server has to be running before I can connect the client, so I thought I could use the before_first_request decorator to make sure I only attempt to connect the client after the server has started. However every time I try, I get:
socketio.exceptions.ConnectionError: Connection refused by the server
At this point the server is definitely running, but no connections will be accepted. If I were to comment out the sockio_client.connect in server.py, and connect from an entirely separate script, everything works as expected. What am I doing wrong? Also, if there are much better ways to do this, please tear it apart.
i see something like this in bottle.py version 0.9. Does that means. i can run bottle server as a eventlet server.
class EventletServer(ServerAdapter):
""" Untested """
def run(self, handler):
from eventlet import wsgi, listen
wsgi.server(listen((self.host, self.port)), handler
)
Atlast figured out. how to run bottle server as eventlet in bottle framework.Just should pass the argument server='' inside run. list of supported servers Server adapters in bottle
run(server='eventlet',host='localhost', port=8080, reloader=True)