现在在用flask实现一个简单的webserver,为了与前段进行通信,加入了flask-socketio模块,现在在处理前段发送过来的消息的函数中直接emit的话,前端可以收到消息。但是想主动发送消息的话失败。具体如下:
在这边的话前端是可以接收到emit发送的消息的。
@socketio.on('request_for_response')
def handle_request(request):
print('received socket message:' + json.dumps(request))
# 这里可以直接发送,如果单独发送就不可以?
emit('response', 'ok')
msgTranslate(request)
如果在普通函数里直接调用就会失败,这里的emit始终不能发送消息。
def recvThread():
while True:
# print("recvThread start---")
msgNum = c_long(0)
content = create_string_buffer(1024)
if recvMsg(byref(msgNum), content) == 0:
print(content)
print("the content number is %d, the content is:%s" % (msgNum.value, content.value))
# 必须要全局的才能调用
d = dict(name='djj', age=26)
print(json.dumps(d))
# response(json.dumps(d))
socketio.emit('response')
socketio定义如下
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app, async_mode=async_mode)
前端代码如下:
var $SCRIPT_ROOT = {{ request.script_root|tojson|safe }};
var socket = io.connect($SCRIPT_ROOT);
socket.on('connect',function()
{
socket.emit('connected');
});
socket.on('response', function(data)
{
console.log(data);
alert("receive response");
/*
if(data.code == '200'){
alert(data.param);
}
else
{
alert('Error:'+data.param);
}
*/
//alert(data.param);
});
$(document).ready(function(){
$("#btn").click(function () {
socket.emit('request_for_response', JSON.stringify({
'ip': $("#ip").val(),
'cover': $("#cover").val(),
'gate': $("#gate").val(),
}));
});
});
发现一个问题:socketio.emit放在线程里就无法执行,我现在的启动的部分代码是这样的,
if __name__ == '__main__':
loadDjjque()
isInit = queInit()
setCharacter(1)
if isInit == 0:
print("--queInit success--")
t = threading.Thread(target=recvThread, name='recvThread')
t.setDaemon(True)
t.start()
socketio.run(app, host='0.0.0.0', port=5555)
但是官方文档写的是:
但对于某些应用程序,服务器需要作为消息的发起者。 这可以用于向客户端发送在服务器中发起的事件的通知,例如在后台线程中。 可以使用socketio.send()和socketio.emit()方法向所有连接的客户端进行广播:
def some_function():
socketio.emit('some event', {'data': 42})
请注意,socketio.send()和socketio.emit()与上下文感知send()和emit()不同。 还要注意,在上面的用法中没有客户端上下文,所以broadcast=True,不需要指定。
作者:1994宅猫
链接:https://www.jianshu.com/p/411...
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
不知道为什么不可以发送出去??
解决问题了,目前问题解决有两种方法!
1、在web发送回来的消息中 通过set_background_tsk()来开启新线程,但是要注意在这个线程中如果需要sleep,必须要用
socketio.sleep()
这样Flask才会放开消息循环,不然整个通信会阻塞。代码如下:
实际上这种方法还是同步的,整个流程的发起还是web,并没有实现正真意义上的互相通信。但是也可以解决现有问题。
2、使用
app.app_context()
,其实socketio.emit()没有发送成功是因为 没有找到app的上下文,使用with app.app_context()
即可以找到app的上下文。但是要注意的是线程中的挂起方式还是得用socketio.sleep()
具体代码如下:
在这个方法中可以做到真正意义上的server端主动发起消息,建议采用后面一种方法