配置
nginx
让socket.io 顺利走到后方,因为 这个 io只认一级目录,socket.io
但是的 server 是由path 参数可做设定的. 我觉他client也能吧.只是二级目录有点太绕.不去试了
1.1.1.30 :9000 nginx转到
1.1.1.25:7005 socketio, app
bash
http {
# 基本HTTP服务器配置
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 9000;
location /socket.io {
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://1.1.1.25:7005/socket.io;
}
其次必须让 socketio开跨域访问,因为,中间有代理nginx,它知道是默认阻止的。
bash
socketio = SocketIO(app,cors_allowed_origins="*" ,message_queue= app.config['REDIS_URL'])
* 号可以是上面nginx在所在地址
最大的意外是html。
bash
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Flask-SocketIO 示例</title>
<script type="text/javascript" src="/js/socket.io.min.js"></script>
<script type="text/javascript" charset="utf-8">
var socket = io.connect('http://1.1.1.30:9000/chat' );
socket.on('my event', function (data) {
// console.log('服务器发送:', data);
// socket.emit('mess', '用户已连接');
// alert('服务器发送:');
虽然 var socket = io.connect('http://1.1.1.25:9000/chat' ); 建立连接是代理走代理。但这个地址被代理阻止的,如果是url,因为nginx开了认证,。但是websocket不吃认证这一天. 而且表面是http,却是后扩展的,用法如同socket
转为 1.1.1.30:9000/socket.io ,去询问server chat是哪位.
根据/chat.得到下面的处理handle
bash
@socketio.on('mess' ,namespace='/chat')
def handle_mess(message):
socketio.emit('mess', {'data': message}, namespace='/chat')
@socketio.on('message' ,namespace='/chat')
def handle_message(message):
socketio.emit('message', {'data': '左右!'}, namespace='/chat')
print(message+"from where......")
if __name__ == '__main__':
# app.run(debug=True,host="0.0.0.0",port=5005)
这样在原有点名后台基础上,加入了在线会话提醒的功能。避免 了反复刷新架构。
bash
给站名加入闪烁,提示刷新
function blink(abc) {{
$($('span:contains("'+abc+'")')[0]).fadeOut(500).fadeIn(500, blink.bind(null,abc));}}
</script>
我也只是又一次瞎猫碰到了死耗子
这里没说我的问题,只是说了最后的设计。我的问题是,所有功能在一个,二级目录下。因为static是nginx的。而flask,是 /api下的。 nginx始终只有一个端口号来的。这让我想用 、/api/chat这样的结构。做为 io.connect('http://1.1.1.30:9000/api/chat' ); 而这中间,隔了 ,一个nginx代理片段。一个app的跨域请求要求。
在突然两个都满足的时候。转了一圈通信建立了。
那么说会redis。 我的所有会议机,可以用websocket请求。但是,我是没有那么大需要。因为我没有回送数据的需要。 只有各点的提交信息,需要我去及时看。而不是一次刷新全部站点。
所以,我在提交数据时给,redis队列一个消息。在得到消息后,通过socketio给中央的控制。提醒收到一个新消息。
而且,在开通gevent,第一次使用 redis 做它的队列的时候要求,在app的开头加入
在linux 启用 redis队列后.gevent 报错.
bash
from gevent import monkey; monkey.patch_all()
感觉这个效果并不是太好。但是能用。
继续死守耗子洞口。
因为不太明白是否需要所有客户端都用websocket建立连接。就像开始说。只是总部建立一个。然后不知道怎么让客户发消息来。既然用到了redis。队列,就想也用,它的订阅吧。 接收订阅是个长期任务。
这是百度AI给的flask-soketio 接收redis的订阅 回答
bash
from flask import Flask, render_template
from flask_socketio import SocketIO
import redis
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
@app.route('/')
def index():
return render_template('index.html')
def subscribe_redis(redis_host, redis_port, redis_channel):
r = redis.StrictRedis(host=redis_host, port=redis_port)
pubsub = r.pubsub()
pubsub.subscribe(**{redis_channel: on_message})
pubsub.run_in_thread(sleep_time=0.01)
def on_message(message):
data = message['data']
socketio.emit('redis_message', data, namespace='/socketio')
if __name__ == '__main__':
# 启动后台任务订阅Redis
socketio.start_background_task(
subscribe_redis,
redis_host='localhost',
redis_port=6379,
redis_channel='my_channel'
)
socketio.run(app, debug=True)
确实不执行。提示socket已关闭。IO不对。然后。我一直在试。直接在python shell 中,subscribe_redis这个函数不阻塞,直接生效。 不错,好用。然而在 flask socket 包装下。一定会出错。 换来换用了一个Threading的另一个订阅方式。还是会出错,几乎一样。切换了python版本。照样。其他功能不受影响。 甚至订阅都是正常的。就是无法放在一起。
接着测试第二个方案。直接给redis中加入 flash-socketio格式的消息。 又得到AI的一个回答,说是 socketio dumps一下,消息的字典。说的没错,但是,人家大人是没有这个字典的。 我觉得经过反编码,是能找到方式的。 但是折腾了一夜。心灰了,dir(socketio)看到了。emit 、提交消息的函数。
既然整个app文件,socketip随便用,拿来发送消息就行了。于是每个点到人名的提交url中。都会发一个人名消息给中心这里。是通过websocket提交的。是即时的。
这样只有一个页面会连接到websocket 。会有消息但不是最终状态。知道一个大概。前期页面第个人名都是<a href id="姓名"
bash
function blink(abc) {{
$(abc).fadeOut(500).fadeIn(500, blink.bind(null,abc));}}
var socket = io.connect('http://1.1.1.30:9000/chat' );
socket.on('mess', function(msg) {
blink('#'+msg.data)
})
</script>
这样一个闪烁就做好了。
bash
@app.route("/docheck/<sta>/<person>")
def check(sta,person):
r=cl.sadd(f"check:{sta}",person)
socketio.emit('mess', {'data': person}, namespace='/chat')
效率和优美就诞生了。
由于意外
lfask人的接口文件, main,和 sta,混用. 把socketio的脚本带到了,所有参会主机.好在能用. 其他地点人员被点名. 此处,每处都会有同名人的提醒.
有点担心,性能损失. 每个会点不过.只有几分钟的在线时间.应该不会有影响.