Клиент Python GUI, который управляет приложением iOS с помощью самозаверяющего сертификата SSL, зависает/перестает обменPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Клиент Python GUI, который управляет приложением iOS с помощью самозаверяющего сертификата SSL, зависает/перестает обмен

Сообщение Anonymous »

Справочная информация: у меня есть самоподписанный сертификат SSL для локального сервера, использующего мобильную точку доступа. Я запускаю этот сервер wss://, используя Ubuntu, поскольку первый клиент находится на компьютере с Windows. Второй клиент — это приложение iOS на физическом iPhone.
Проблема: все подключается и взаимодействует хорошо, но после примерно 600 с лишним секунд потоковой передачи данных (запись данных о местоположении в файл .csv), клиент драйвера графического интерфейса Python зависает и прекращает взаимодействие с приложением iOS и управление им. Я много раз тестировал, и оно всегда останавливается на отметке 600–700 секунд, а файлы .csv также всегда имеют размер около 1500–1600 КБ.
Может кто-нибудь понять, почему графический интерфейс Python клиент зависает через ~600 секунд (около 1500 КБ данных)? Я считаю, что проблема заключается в разделе «msg = self.receiver.recv()», но не знаю, почему он блокирует/не может получать данные. Есть ли где-нибудь скрытый тайм-аут? Я предоставил свои коды ниже. Я не указал сторону приложения для iOS, поскольку с приложением проблем нет, а графический интерфейс Python — это сторона, которая зависает/останавливается.
Изображение

Ниже приведен клиент Python с графическим интерфейсом для управления приложением iOS:
import sys
import csv
import base64
import threading
from time import time,sleep
from datetime import datetime
from glob import glob
from os import rename, path, listdir

import logging
logging.basicConfig(level=logging.INFO)

# Import remaining modules
from webSocketServerClient import getServer,getClient
from PyQt5 import QtGui
from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QThread
from PyQt5.QtWidgets import QWidget, QApplication, QLabel, QVBoxLayout, QHBoxLayout, QPushButton, QComboBox, QFileDialog, QLineEdit
from PyQt5.QtGui import QPixmap
from pandas import read_excel
import cv2
import numpy as np

from audio_drawing import PozClient
from nearest_barrier import proximity_map_from_png

class VideoThread(QThread):
change_pixmap_signal = pyqtSignal(np.ndarray)
send_map_to_client = pyqtSignal()

def __init__(self, receiver, map_filename):
super().__init__()
self.run_flag = True
self.change_map_flag = True
self.receiver = receiver
self.map_filename = map_filename
self.pozClient = PozClient(map_filename)
self.log_header = []
self.log_filename = ""
self.log_flag = "wait"

def run(self):
self.run_flag = True
csvwriter = None
i = 0

while self.run_flag:
# Map handling
if self.change_map_flag or 'map' not in locals():
fn = self.map_filename
map = cv2.imread(fn)
print(f'Change map to {self.map_filename}')
self.change_map_flag = False
self.pozClient.update_map(fn)

# Log file handling
if self.log_flag == "stop":
if self.logfile is not None:
self.logfile.close()
print(f"Closing file: {self.log_filename}")
self.logfile = None
else:
print("Warning, no log file to close.")
self.log_flag = "wait"
self.pozClient.mute_tone()

if self.log_flag == "abort":
if self.logfile is not None:
self.logfile.close()
rename(self.log_filename, self.log_filename+'.abort')
print(f"Closing file: {self.log_filename+'.abort'}")
self.logfile = None
self.log_flag = "wait"
self.pozClient.mute_tone()

if self.log_flag == "new":
print(f"Writing to file: {self.log_filename}")
self.logfile = open(self.log_filename, 'w', newline='')
for header_line in self.log_header:
self.logfile.write(header_line)
csvwriter = csv.writer(self.logfile, delimiter=',')
self.log_flag = "write"
self.pozClient.unmute_tone()

# Get a fresh copy of the map to draw on top of
cv_img = map.copy()

msg = self.receiver.recv()
txt = msg.split()

if len(txt) == 10:
try:
if self.log_flag == "write":
csvwriter.writerow(txt[2:])
self.logfile.flush()
xf = float(txt[2])*100 + 300
yf = 300 - float(txt[3])*100
theta = -float(txt[6])
i += 1
cv_img = self.pozClient.oneStep(xf,yf,theta,i)
except:
pass
else:
if 'SendMap' in msg:
sleep(.01)
self.send_map_to_client.emit()
if 'time' not in msg:
print(msg)
if self.log_flag != "write":
txt = 'Waiting for data stream...'
thickness=2
size=1
cv2.putText(cv_img, txt, (25,100), cv2.FONT_HERSHEY_SIMPLEX, size, (0,0,255), thickness)
# Always update the display
self.change_pixmap_signal.emit(cv_img)

def stop(self):
"""Sets run flag to False and waits for thread to finish"""
self.end_log()
sleep(.05)
self.run_flag = False
sleep(.1)
del self.pozClient
#self.wait()

def change_map(self, map_filename):
if self.map_filename != map_filename:
self.map_filename = map_filename
self.change_map_flag = True
#self.stop()
#self.pozClient.update_map(map_filename)
#self.run()

def start_log(self, header):
timestamp_string = datetime.now().strftime("%Y.%m.%d_%H.%M.%S")
self.log_filename = "logs/" + timestamp_string + "_log.csv"
# Only create a new log file from a "wait" state
if self.log_flag == "wait":
self.log_flag = "new"
header_row = "X,Y,Z,angle0,Theta,angle2,Timestamp,TrackingStatus"
null_row = f"0,0,0,0,0,0,0,0"
for title, entry in header.items():
header_row += f",{title}"
null_row += f",{entry}"
self.log_header.clear()
self.log_header.append(header_row + "\n")
self.log_header.append(null_row + "\n")
else:
print("Warning, already logging")

def end_log(self):
self.log_flag = "stop"

def abort_log(self):
self.log_flag = "abort"

Ниже приведен код создания сервера WebSocket:
import socketserver
import ssl
import logging
import threading
import struct
import hashlib
import base64
from time import time, sleep
import websocket
import os

logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger('WebSocketServer')

class SimpleChat(http.server.BaseHTTPRequestHandler):
clients = []
clients_lock = threading.Lock()
magic = b'258EAFA5-E914-47DA-95CA-C5AB0DC85B11' # Added WebSocket magic string

def setup(self):
super().setup()
self.connected = False
self.request = self.connection
self.send_lock = threading.Lock()
self.last_activity = time()
self.address = None

def handleMessage(self):
try:
message = self.read_frame()
if message:
with SimpleChat.clients_lock:
active_clients = [c for c in self.clients if c.connected]
self.clients = active_clients

for client in active_clients:
if client != self and client.connected:
try:
client.safe_write(f"{self.address[0]} - {message}")
except Exception as e:
logger.error(f"Send error: {e}")
client.connected = False
except Exception as e:
logger.error(f"Handle message error: {e}")
self.connected = False

def handleConnected(self):
self.address = self.client_address # Set address when connection established
logger.info(f"{self.address} connected")
with SimpleChat.clients_lock:
self.clients.append(self)
# Notify other clients
for client in self.clients:
if client != self and client.connected:
try:
client.safe_write(f"{self.address[0]} - connected")
except Exception as e:
logger.error(f"Connection notification error: {e}")
client.connected = False

def handleClose(self):
self.connected = False
if hasattr(self, 'address') and self.address: # Check if address exists
with SimpleChat.clients_lock:
if self in self.clients:
self.clients.remove(self)
# Notify other clients
for client in self.clients:
if client.connected:
try:
client.safe_write(f"{self.address[0]} - disconnected")
except Exception as e:
logger.error(f"Disconnection notification error: {e}")
client.connected = False
logger.info(f"{self.address} closed")
else:
logger.info("Connection closed before initialization")

def do_GET(self):
if 'Upgrade' not in self.headers:
self.send_error(426, "Upgrade Required")
return

if self.headers.get('Upgrade', '').lower() != 'websocket':
self.send_error(400, "Can only upgrade to WebSocket")
return

if 'Sec-WebSocket-Key' not in self.headers:
self.send_error(400, "Missing WebSocket Key")
return

try:
key = self.headers['Sec-WebSocket-Key']
accept = base64.b64encode(
hashlib.sha1(key.encode() + self.magic).digest()
).decode()

# Send response with HTTP/1.1
self.protocol_version = 'HTTP/1.1'
self.send_response_only(101)
self.send_header('Upgrade', 'websocket')
self.send_header('Connection', 'Upgrade')
self.send_header('Sec-WebSocket-Accept', accept)
self.end_headers()

self.connected = True
self.address = self.client_address # Set address before handling connection
self.handleConnected()

while self.connected:
self.handleMessage()

except Exception as e:
logger.error(f"WebSocket error: {e}")
self.connected = False

finally:
self.handleClose()

def safe_write(self, message):
"""Thread-safe method to write WebSocket messages"""
try:
with self.send_lock:
if isinstance(message, str):
message = message.encode('utf-8')

header = bytearray()
header.append(0x80 | 0x1) # Text frame

length = len(message)
if length

Подробнее здесь: https://stackoverflow.com/questions/792 ... reezing-st
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»