gpt4 book ai didi

python - 如何使用 Flask-Socket IO 从服务器向客户端发送消息

转载 作者:行者123 更新时间:2023-11-28 19:53:13 25 4
gpt4 key购买 nike

我正在尝试创建一个可以从服务器向客户端发送消息的 python 应用程序。目前我正在使用来自 here 的示例代码.这是一个聊天应用程序,运行良好。我尝试修改应用程序并在服务器端 python 代码中添加一个新函数,该函数将向客户端打印一条消息“Dummy”,但似乎没有用。

这是我的 html 代码:

index.html

<body>
<ul id="messages"></ul>
<ul id="output"></ul>
<form action="">
<input id="m" autocomplete="off" /><button>Send</button>
</form>

<script src="{{url_for('static', filename='assets/vendor/socket.io.min.js')}}"></script>
<script src="{{url_for('static', filename='assets/vendor/jquery.js')}}"></script>

<script>
var socket = io.connect('http://127.0.0.1:5000/chat');

$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});

socket.on('chat message', function(msg){
$('#messages').html($('<li>').text(msg));
});

socket.on('output', function(msg){
alert(msg)
$('#messages').html($('<li>').text(msg));
});
</script>

这是我的后端代码:

web_app.py

from flask import Flask
from flask import render_template
from flask_socketio import SocketIO
from flask_socketio import emit

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
connected = False

def socket_onload(json):
socketio.emit('output', str(json), namespace='/chat')
print('received message: ' + str(json))


@socketio.on('chat message', namespace='/chat')
def handle_chat_message(json):
print('received message: ' + str(json))
emit('chat message', str(json), broadcast=True)


@socketio.on('connect') # global namespace
def handle_connect():
global connected
connected = True
print('Client connected')

@socketio.on('connect', namespace='/chat')
def handle_chat_connect():
print('Client connected to chat namespace')
emit('chat message', 'welcome!')

@socketio.on('disconnect', namespace='/chat')
def test_disconnect():
print('Client disconnected')


@app.route('/')
def index():
return render_template('index.html')


@app.route('/blah/')
def blah():
return render_template('blah.html')

主.py

import web_app
import threading
import time

def main():
import web_app
webapp_thread = threading.Thread(target=run_web_app)
webapp_thread.start()
# webapp_thread = threading.Thread(target=run_web_app, args=(i,))

while web_app.connected==False:
print "waiting for client to connect"
time.sleep(1)
pass

print "Connected..."
time.sleep(3)
print "Trying to print dummy message..."
web_app.socket_onload("Dummy")

def run_web_app():
web_app.socketio.run(web_app.app)

if __name__ == '__main__':
main()

我可以在终端中看到“收到消息:Dummy”,但网络浏览器上没有任何变化。

最佳答案

你有两个错误阻止你这样做:

首先,您尝试在套接字上下文之外使用 socket.io 发出事件。

当函数被 @socketio.on 包装时装饰器,它变成了一个 Event-Handlers .当在服务器端触发事件时,它将搜索正确的处理程序来处理事件并将上下文初始化为发出事件的特定客户端。

如果没有这个上下文初始化,你的 socketio.emit('output', str(json), namespace='/chat')什么都不做,因为服务器不知道应该将响应发回给谁。

无论如何,手动特定客户端发送事件有一个小技巧(即使您不在其上下文中)。每次打开套接字时,服务器都会将其分配给与套接字 ID (sid) 同名的“私有(private)”房间。因此,为了从客户端上下文向客户端之外的客户端发送消息,您可以创建连接的客户端 ID 列表并使用 room=<id> 调用 emit 函数。争论。

例如:

web_app.py:

...
from flask import Flask, request

clients = []

@socketio.on('connect')
def handle_connect():
print('Client connected')
clients.append(request.sid)

@socketio.on('disconnect')
def handle_disconnect():
print('Client disconnected')
clients.remove(request.sid)

def send_message(client_id, data):
socketio.emit('output', data, room=client_id)
print('sending message "{}" to client "{}".'.format(data, client_id))

...

那么您可能会按如下方式使用它:

ma​​in.py:

import web_app
import threading
import time

def main():
webapp_thread = threading.Thread(target=run_web_app)
webapp_thread.start()

while not web_app.clients:
print "waiting for client to connect"
time.sleep(1)

print "Connected..."
time.sleep(3)
print "Trying to print dummy message..."
web_app.send_message(web_app.clients[0], "Dummy")

...

但即使你尝试这样做,它也不会起作用(这给我们带来了第二个错误)。


其次,您将 eventlet 与常规 Python 线程混合使用,这不是一个好主意。 eventlet 使用的绿色线程不适用于常规线程。相反,您应该使用绿色线程来满足您的所有线程需求。

我在互联网上找到的一个选项是对 Python 标准库进行猴子修补,以便将线程、套接字等替换为 eventlet 友好版本。您可以在 main.py 脚本的最顶部执行此操作:

import eventlet
eventlet.monkey_patch()

之后它应该可以正常工作(我自己试过了)。如果您还有其他问题,请告诉我...

关于python - 如何使用 Flask-Socket IO 从服务器向客户端发送消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45918818/

25 4 0