how to get connected clients in flask

て烟熏妆下的殇ゞ 提交于 2020-11-30 01:50:16

问题


hi i need to display total number of connected clients on my flask app i write this code for checking connected and disconnected connections.

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)

then i render template like this

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

In html part i call like this

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

but on webpage it keep showing 0 even client is connect i get output from client and it is connected it should print 1 2 depends how many clients are connected. even if i print this print(len(clients)) it return 0. even my client is connect and i get output.

this is my updated code

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)

Client Side :

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)
        

回答1:


After reading a bit of socket.io documentation I've managed to spot the problems in your code.

Not a problem per-se, but incrementing/decrementing an int counter is more than enough for this use case. Secondly, you don't have to pass that counter to the render_template call as you're basically passing the user count before the conenct event has had the opportunity to fire. You should emit a message (in this example with a users topic) that will inform your page that something has changed:

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)

Moreover, you didn't open a connection to the socket in your template, this allows you to listen to the messages emitted by your socketio decorators and update all connected clients. You will also need to write a bit of javascript to specify that the counter needs to be updated anytime a user connects/disconnects.

<!-- 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 -->

This being said, you don't need to pass the counter value in your render_template call. Also, from flask-socketio docs, it seems to be good practice to start your app in the following way:

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

Here a link to an edited version of your example.



来源:https://stackoverflow.com/questions/64197037/how-to-get-connected-clients-in-flask

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!