【问题标题】:how to get connected clients in flask如何在烧瓶中获得连接的客户端
【发布时间】:2021-01-19 15:14:57
【问题描述】:

您好,我需要在我的烧瓶应用程序上显示已连接客户端的总数我编写此代码用于检查连接和断开连接。

app = Flask(__name__)
socketio = SocketIO(app)
clients = []

@socketio.on('connect', namespace='/')
def connect():
    clients.append(request.namespace)

@socketio.on('disconnect', namespace='/')
def disconnect():
    clients.remove(request.namespace)

然后我像这样渲染模板

return render_template_string(TABLE_TEMPLATE, data=data, clients=len(clients))

在html部分我这样称呼

<h1>{{ clients }} </h1>

但在网页上它一直显示0 即使客户端连接我从客户端获取输出并且它已连接它应该打印1 2 取决于连接了多少客户端。即使我打印这个 print(len(clients)) 它也会返回0。甚至我的客户端也已连接,我得到了输出。

这是我更新的代码

from flask import Flask, request, render_template_string
from flask_socketio import SocketIO, emit

app = Flask(__name__)
socketio = SocketIO(app, logge=True)
clients = 0

@socketio.on("connect", namespace="/")
def connect():
    # global variable as it needs to be shared
    global clients
    clients += 1
    # emits a message with the user count anytime someone connects
    emit("users", {"user_count": clients}, broadcast=True)

@socketio.on("disconnect", namespace="/")
def disconnect():
    global clients
    clients -= 1
    emit("users", {"user_count": clients}, broadcast=True)


TABLE_TEMPLATE = """
<script
src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.7.3/socket.io.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
    $(document).ready(function(){
        var namespace = '/';    
        var socket = io.connect('http://' + document.domain + ':' + location.port + namespace);
        // Update the counter when a new user connects
        socket.on('users', function(users) {
            userCount = document.getElementById('user_counter');
            userCount.innerHTML = users.user_count;
        });
});
</script>
<h1 id='user_counter'></h1>
<style>
   table, th, td {
   border: 1px solid black;
   }
</style>
<table style="width: 100%">
   <thead>
      <th>Client</th>
      <th>IP</th>
      <th>Status</th>
   </thead>
   <tbody>
      {% for row in data %}
      <tr>
         <td><center>{{ row.client }}</td></center>
         <td><center>{{ row.ip }}</td></center>
         <td><center>{{ row.status }}</td></center>
      </tr>
      {% endfor %}
   </tbody>
</table>
"""


@app.route("/device_add", methods=['POST'])
def device_add():
    name = request.args.get('name')
    with open('logs.log', 'a') as f:
        f.write(f'{name} Connected USB from IP: {request.remote_addr} \n')
    return 'ok'


@app.route("/device_remove", methods=['POST'])
def device_remove():
    name = request.args.get('name')
    with open('logs.log', 'a') as f:
        f.write(f'{name} Disconnected USB from IP: {request.remote_addr}\n')

    return 'ok'


@app.route("/", methods=['GET'])
def device_list():
    keys = ['client', 'ip', 'status']
    data = []
    with open('logs.log', 'r') as f:
        for line in f:
            row = line.split()
            data.append(dict(zip(keys, [row[0], row[-1], row[1]])))


    return render_template_string(TABLE_TEMPLATE, data=data)


if __name__ == "__main__":
  socketio.run(app)

客户端:

import requests
import subprocess, string, time
import os

url = 'http://127.0.0.1:5000/'
name = os.uname()[1]

def on_device_add():
    requests.post(f'{url}/device_add?name={name}')
def on_device_remove():
    requests.post(f'{url}/device_remove?name={name}')

def detect_device(previous):
    total = subprocess.run('lsblk | grep disk | wc -l', shell=True, stdout=subprocess.PIPE).stdout
    time.sleep(3)

    # if condition if new device add
    if total > previous:
        on_device_add()
    # if no new device add or remove
    elif total == previous:
        detect_device(previous)
    # if device remove
    else:
        on_device_remove()
    # Infinite loop to keep client running.


while True:
    detect_device(subprocess.run(' lsblk | grep disk | wc -l', shell=True , stdout=subprocess.PIPE).stdout)
        

【问题讨论】:

  • 在连接和断开连接事件中添加几个打印语句,似乎 socketio 事件没有正确触发。虽然不太确定是什么导致了问题......

标签: python sockets flask


【解决方案1】:

在阅读了一些 socket.io 文档后,我设法发现了您代码中的问题。

本身不是问题,但是对于这个用例来说,增加/减少 int 计数器已经绰绰有余了。其次,您不必将该计数器传递给render_template 调用,因为您基本上是在conenct 事件有机会触发之前传递用户计数。您应该发出一条消息(在本例中为 users 主题),通知您的页面发生了一些变化:

from flask import Flask, request, render_template_string
from flask_socketio import SocketIO, emit

app = Flask(__name__)
socketio = SocketIO(app, logge=True)
clients = 0

@socketio.on("connect", namespace="/")
def connect():
    # global variable as it needs to be shared
    global clients
    clients += 1
    # emits a message with the user count anytime someone connects
    emit("users", {"user_count": clients}, broadcast=True)

@socketio.on("disconnect", namespace="/")
def disconnect():
    global clients
    clients -= 1
    emit("users", {"user_count": clients}, broadcast=True)

此外,您没有在模板中打开与套接字的连接,这使您可以监听 socketio 装饰器发出的消息并更新所有连接的客户端。您还需要编写一些 javascript 来指定在用户连接/断开连接时需要更新计数器。

<!-- Remember to import socketio library -->
<script
src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.7.3/socket.io.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
    $(document).ready(function(){
        var namespace = '/';    
        var socket = io.connect('http://' + document.domain + ':' + location.port + namespace);
        // Update the counter when a new user connects
        socket.on('users', function(users) {
            userCount = document.getElementById('user_counter');
            userCount.innerHTML = users.user_count;
        });
});
</script>
<h1 id='user_counter'></h1>
<!-- the rest of your template -->

话虽如此,您不需要在您的render_template 调用中传递计数器值。 此外,从flask-socketiodocs 开始,按照以下方式启动您的应用程序似乎是一种好习惯:

if __name__ == "__main__":
    socketio.run(app)

Here 指向您示例的编辑版本的链接。

【讨论】:

  • 您好,谢谢您,但有一个问题,我在连接任何客户端之前运行您的代码,如果我刷新它会增加 2、3 等,即使没有客户端连接,也会说 1 客户端连接
  • 这对我来说看起来不错,只是您不需要在启动应用程序时需要传递threaded 参数。还有,不用导入typing.Counter,你为什么这么做?
  • 我改变了一切,但它一直显示 1 客户端连接 2 连接等等,即使没有 1 连接。我更新帖子
  • 没错,如果您正在查看该页面,那么您的浏览器将是已连接的客户端(因此 1 个客户端已连接)
  • 不,我在运行客户端代码时更新了我的帖子,那么它应该需要显示客户端已连接或 1 个客户端我没有运行我的客户端代码但它一直显示 1 个客户端
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-29
  • 1970-01-01
  • 2021-01-14
  • 1970-01-01
  • 1970-01-01
  • 2022-08-08
  • 2020-06-04
相关资源
最近更新 更多