2017-08-28 43 views
0

我试图创造一个Python应用程序,可以从服务器发送消息给客户端发送消息给客户端。目前我使用here这个示例代码。这是一个聊天应用程序,它工作正常。我试图修改应用程序,并在服务器端Python代码中添加一个新功能,该功能将在客户端打印一条消息“Dummy”,但看起来不起作用。如何从服务器使用瓶套接字IO

这里是我的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') 

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() 

我可以看到“收到的消息:虚拟”在终端,但没有对网络浏览器的变化。

+0

很难知道,而无需一个完整的例子来进行测试。您是否在浏览器的控制台中查看是否有任何错误? – Miguel

回答

0

这些装饰都是在那里只需加载index.html的页面和blah.html这些没有做任何事情---不传递任何变量或不写什么模板,他们只是使其,同时所有的东西你正在做的是那里的命令行,如果你要打印或通过任何它必须是在这些功能:

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


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

它在'Thread'的'target ='中。 –

1

你有错误,其阻止你这样做:

第一,您正尝试从套接字上下文之外的socket.io发出事件。

当一个函数被@socketio.on修饰器包装时,它将变成Event-Handlers。 虽然事件是在服务器端的发射将寻找正确的处理程序来处理事件和初始化的背景下发出该事件的特定的客户端。

没有这方面的初始化,您socketio.emit('output', str(json), namespace='/chat')会做任何事情,因为服务器不知道谁应发出回响应。

反正有手动发射事件特定客户(即使你是不是在它的上下文中)的一个小动作。每次打开套接字时,服务器都会将其分配给与套接字标识(sid)具有相同名称的“私人”空间。因此,为了从客户方面将消息发送到客户端外,您可以创建连接的客户端ID的列表,并调用与room=<id>参数信号发送的功能。

例如:

web_app。潘岳:

... 

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) 

... 

那么你可能会使用这个如下:

main.py:

import web_app 
import threading 
import time 

def main(): 
    webapp_thread = threading.Thread(target=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") 

... 

但是,即使你试试这个,这是不行的(这使我们到了第二个错误)。


,你用常规的Python线程混合eventlet,它是不是一个好主意。 eventlet使用的绿色线程对常规线程无效。相反,您应该使用绿色线程来满足您的所有线程需求。

一个选择,我在互联网上找到,是猴子修补Python标准库,使线程,插座等与eventlet友好的版本替换。您可以在main.py脚本的最顶部做到这一点:

import eventlet 
eventlet.monkey_patch() 

之后,它应该工作正常(我尝试了我自己)。让我知道如果您有其他问题...

+0

感谢您的回答。但它仍然没有工作。控制台日志中也没有错误。只是一个问题,什么是实现实时python-html更新的最佳方式/库?似乎像flask-socketio没有直接的方法来做到这一点。我唯一的意图是有一个python模块将其他python模块的输出推送到html。 – nyamuk91

+0

所以我不明白你为什么要为此创建一个单独的线程。你能给我一个你需要的例子吗?我认为你可以从socket.io服务器线程开始你的动作,并且只有当你想使用'socketio.start_background_task'函数执行一个后台任务。 – AlonP

+0

对不起,我很新瓶。我创建一个单独的线程的原因是因为'web_app.socketio.run(web_app.app)'行阻止了进一步的进程。 所以我目前正在开发一个用户的计算机“对话”的应用程序,将用户的语音作为输入>使用沃森STT其转录成文本>发送到沃森通话服务>摆脱在Python沃森>显示响应响应。这部分已经完成。所以现在,我计划还将输入(转录文本)和沃森的回应显示在网页中(实时) – nyamuk91

相关问题