我正在尝试创建一个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>
这是我的后台代码:
网络应用程序.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')
main.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()
我可以在终端中看到“received message:Dummy”,但在web浏览器上没有任何变化。
这些decorator用于简单地加载页面
index.html
和blah.html
,它们不做任何事情---不传递任何变量或不向模板写入任何内容,它们只是呈现模板,同时,如果必须打印或传递任何内容,则您正在执行的所有操作都用于命令行,这些函数中必须包含:您有两个错误阻止您这样做:
首先,您试图从套接字上下文外部发出socket.io事件。
当函数被
@socketio.on
decorator包装时,它将成为Event-Handlers
。 当在服务器端触发事件时,它将搜索正确的处理程序来处理该事件,并将上下文初始化到发出该事件的特定客户端。如果不初始化此上下文,您的
socketio.emit('output', str(json), namespace='/chat')
将不会执行任何操作,因为服务器不知道应该向谁发出响应。无论如何,有一个小技巧可以将事件手动发送到特定客户机(即使您不在其上下文中)。每次打开一个套接字时,服务器都会将其分配给一个与套接字id同名的“专用”房间(
sid
)。因此,为了从客户机上下文向外部客户机发送消息,可以创建连接的客户机的id列表,并使用room=<id>
参数调用emit函数。例如:
网络应用程序。py:
那么您可能会使用以下方式:
main.py:
但即使你尝试了这个,它也不会起作用(这就带来了第二个错误)。
秒,您正在将eventlet与常规Python线程混合,这不是一个好主意。eventlet使用的绿色线程不能与常规线程一起正常工作。相反,您应该使用绿色线程来满足您的所有线程需求。
我在因特网上找到的一个选项是对Python标准库进行monkey补丁,以便用eventlet友好版本替换线程、套接字等。您可以在main.py脚本的最顶端执行此操作:
在那之后它应该可以工作(我自己试过)。如果你有其他问题请告诉我。。。
相关问题 更多 >
编程相关推荐