向特定用户发出的 SocketIO(不为每个客户端使用单独的房间)

Posted

技术标签:

【中文标题】向特定用户发出的 SocketIO(不为每个客户端使用单独的房间)【英文标题】:SocketIO to emit to a particular user (without using separate room for every client) 【发布时间】:2021-06-11 02:24:34 【问题描述】:

我正在尝试开发一个支持后端长时间任务的 Web 应用程序。我在我的服务器上使用flask-socketio 包和芹菜。我的工作流程如下:

    当客户端打开 html 页面时,我会启动与服务器的套接字连接,该连接会为用户创建一个 uid 并将其发回。 现在,一旦用户发布长任务请求——我使用 celery 安排它,一旦完成,我需要将它发送给发布请求的用户。 (我在发布请求中存储了相关的用户 ID)

我查看了@Miguels 对39423646/flask-socketio-emit-to-specific-user 的回答,它为每个用户创建了一个单独的房间,然后在该房间广播消息。但是我想问一下是否有其他更简单的方法可以做到这一点,因为这样做似乎效率低下或强制执行。

我还遇到了 nodejs 解决方案 (how-to-send-a-message-to-a-particular-client-with-socket-io),我觉得这是一种更自然的方式来实现这一点。 python-socketio中是否也有类似的解决方案?


更新:经过更多搜索后,我在 github gist 上发现了 following solution。据此 -- ** flash-socketIO 已经将所有客户端放在request.sid ** 给出的单独房间中。

我仍然希望讨论其他方法来做到这一点。 特别是如果网站流量非常高 - 会不会导致房间过多?


更新 (2)我当前(工作)的服务器代码使用房间。这是从flask-SocketIO celery example借用和修改的

@celery.task(bind=True)
def long_task(self, userid, url):
    # LONG TASK
    time.sleep(10)
    # meta = some result
    post(url, json=meta) 
    # It seems i can't directly emit from celery function so I mimic a post request and emit from that function 
    return meta

@app.route('/longtask', methods=['POST'])
def longtask():
    userid = request.json['userid']
    task = long_task.delay(elementid, userid, url_for('event', _external=True))
    return jsonify(), 202

@socketio.on('connect', namespace='/custom')
def events_connect():
    userid = str(uuid.uuid4())
    session['userid'] = userid
    current_app.clients[userid] = request.sid
    emit('userid', 'userid': userid)

@app.route('/event/', methods=['POST'])
def event():
    userid = request.json['userid']
    data = request.json
    roomid = app.clients.get(userid)
    socketio.emit('celerystatus', data, namespace='/custom', room=roomid)
    return 'ok'
    


【问题讨论】:

当客户端将保存self 连接到静态列表或字典(全局)...然后只需使用users[client_id].send(或任何方法)访问该客户端 这里的self是什么?我没有使用基于类的命名空间 嗯,你应该把你的服务器代码......然后有人可以更好地帮助你......至少处理新连接客户端的部分 哦,好吧。我会这样做的。 这能回答你的问题吗? flask socketio emit to specific user 【参考方案1】:

您不必创建任何房间来解决单个用户的问题。只需将to 参数设置为您要寻址的用户的sid

emit('my event', my_data, to=user_sid)

分配给每个用户的sid 值在connect 事件处理程序中作为request.sid 提供给您。

【讨论】:

【参考方案2】:

您可以为每个单独的用户腾出一个房间。并且您可以向特定房间发出您想要分享消息的用户。

io.to(user.room).emit('specific-user',  message );

这里的意思是分离用户房间,你需要定义一个房间id到一个聊天室,就像一个聊天应用程序(一对一通信)。 房间 id 可以连接自己的 id 和用户 id,您要发送消息以获得每个用户的唯一房间 id。

【讨论】:

以上是关于向特定用户发出的 SocketIO(不为每个客户端使用单独的房间)的主要内容,如果未能解决你的问题,请参考以下文章

SocketIO - 如何向特定客户端发送数据

以设定的时间间隔从 flask_socketio 服务器发出事件

使用 Socket IO、Laravel、Redis、Angularjs 向特定用户发送数据

使用 ack SocketIO 与 iOS 发出

如何发出一个 DM 某人但它可以忽略特定用户的命令?

python Flask-socket.io向特定客户端发出