from flask import Flask, redirect, render_template_string, request, jsonify
import threading
import time
app = Flask(__name__)
# Настройки
MAX_CONNECTIONS = 5 # Максимальное число одновременных подключений
SESSION_TIMEOUT = 300 # Таймаут неактивной сессии (сек)
# Хранилище сессий (в памяти)
active_sessions = {} # {session_id: last_active_time}
lock = threading.Lock() # Для потокобезопасности
def cleanup_sessions():
"""Удаляет просроченные сессии"""
now = time.time()
with lock:
for sid in list(active_sessions.keys()):
if now - active_sessions[sid] > SESSION_TIMEOUT:
del active_sessions[sid]
@app.before_request
def before_request():
"""Очищает просроченные сессии перед каждым запросом"""
cleanup_sessions()
@app.route('/')
def index():
# Получаем уникальный идентификатор клиента (например, по IP + User-Agent)
client_id = request.remote_addr + request.headers.get('User-Agent', '')
with lock:
now = time.time()
# Обновляем время последней активности для текущего клиента
if client_id in active_sessions:
active_sessions[client_id] = now
# Уже подключён — перенаправляем на webvisu
return redirect("http://ваш-плк-ip/webvisu")
else:
# Проверяем, есть ли свободное место
if len(active_sessions) < MAX_CONNECTIONS:
active_sessions[client_id] = now
return redirect("http://ваш-плк-ip/webvisu")
else:
# Нет свободных мест — возвращаем 429
return render_template_string('''
<h1>429 Too Many Requests</h1>
<p>Превышено число одновременных подключений.</p>
<p>Пожалуйста, подождите и попробуйте снова через {{ retry_after }} секунд.</p>
''', retry_after=SESSION_TIMEOUT), 429
@app.route('/status')
def status():
"""Вспомогательный маршрут для проверки числа подключений"""
with lock:
return jsonify({
"active_connections": len(active_sessions),
"max_connections": MAX_CONNECTIONS,
"available_slots": MAX_CONNECTIONS - len(active_sessions)
})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, threaded=True)