Сбой клиент-серверного приложения из-за тарабарщины данных при потоковой передаче экрана (OpenCV, сокеты)Python

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Сбой клиент-серверного приложения из-за тарабарщины данных при потоковой передаче экрана (OpenCV, сокеты)

Сообщение Anonymous »

Я создаю клиент-серверное приложение, которое передает данные экрана с клиента на сервер с помощью Python, OpenCV и сокетов. Потоковая передача экрана осуществляется путем захвата снимка экрана на клиенте, его кодирования в формате JPEG и отправки на сервер. Сервер декодирует изображение и отображает его с помощью OpenCV.
Однако, когда я запускаю приложение, сервер получает что-то вроде тарабарщины или поврежденных данных, что в конечном итоге приводит к сбою сервера. Похоже, проблема возникает при получении данных изображения, что приводит к отображению неполных или поврежденных изображений.
Вот что я пробовал:
Using a helper function recv_all() to ensure the full image data is received before decoding.
The client sends the image size first, followed by the actual image data.
Both client and server use a loop to ensure they receive all the data before processing it.

Несмотря на эти усилия, я по-прежнему вижу мусорные или поврежденные данные, и в конечном итоге сервер выходит из строя.
server.py
import socket
import threading
import cv2
import numpy as np
from file_management import receive_file, send_file, execute_file

SERVER_IP = '192.168.68.117'
SERVER_PORT = 60608

def recv_all(conn, size):
data = b''
while len(data) < size:
try:
chunk = conn.recv(4096)
if not chunk:
break
data += chunk
except socket.error:
conn.close()
break
return data

def handle_client(conn, addr):
print(f"Connected to {addr}")
try:
while True:
command = conn.recv(1024).decode(errors='ignore')
if not command:
print(f"Connection closed by {addr}")
break

print(f"Received command: {command}")

if command.startswith("upload"):
filename = command.split(" ")[1]
receive_file(conn, filename)
elif command.startswith("download"):
filepath = command.split(" ")[1]
send_file(conn, filepath)
elif command.startswith("execute"):
filepath = command.split(" ")[1]
execute_file(conn, filepath)
elif command.startswith("screen"):
screen_size_bytes = conn.recv(4)
if not screen_size_bytes:
print(f"Connection closed by {addr}")
break

screen_size = int.from_bytes(screen_size_bytes, 'big')
screen_data = recv_all(conn, screen_size)

if screen_data:
np_img = np.frombuffer(screen_data, dtype=np.uint8)
img = cv2.imdecode(np_img, cv2.IMREAD_COLOR)
if img is not None:
cv2.imshow(f"Remote Desktop - {addr}", img)
cv2.waitKey(1)

print(f"Client {addr} has disconnected.")
except Exception as e:
print(f"Error while handling client {addr}: {str(e)}")
finally:
conn.close()
print(f"Connection closed for {addr}")

def start_remote_desktop_server():
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((SERVER_IP, SERVER_PORT))
server.listen(1)
print(f"Remote Desktop Server listening on {SERVER_IP}:{SERVER_PORT}...")

while True:
try:
conn, addr = server.accept()
print(f"Accepted connection from {addr}")
client_thread = threading.Thread(target=handle_client, args=(conn, addr))
client_thread.start()
except Exception as e:
print(f"Error accepting connection: {str(e)}")

if __name__ == "__main__":
start_remote_desktop_server()


client.py
import socket
import threading
import cv2
import numpy as np
import pyautogui
from file_management import upload_file, download_file, execute_remote_file

SERVER_IP = '192.168.68.117'
SERVER_PORT = 60608

def send_screen(conn):
while True:
try:
screenshot = pyautogui.screenshot()
img_np = np.array(screenshot)
_, img_encoded = cv2.imencode('.jpg', img_np)
img_data = img_encoded.tobytes()
conn.send(len(img_data).to_bytes(4, 'big'))
conn.sendall(img_data)
cv2.waitKey(1)
except Exception as e:
print(f"Error sending screen data: {str(e)}")
break

def recv_all(conn, size):
data = b''
while len(data) < size:
try:
chunk = conn.recv(4096)
if not chunk:
break
data += chunk
except socket.error:
conn.close()
break
return data

def handle_commands(conn):
while True:
command = input("\n \n > ")
if command.startswith("upload"):
filepath = command.split(" ")[1]
upload_file(conn, filepath)
elif command.startswith("download"):
filename = command.split(" ")[1]
download_file(conn, filename)
elif command.startswith("execute"):
filepath = command.split(" ")[1]
try:
execute_remote_file(conn, filepath)
except ConnectionResetError:
print("Connection lost. The server may have closed the connection.")
break
except Exception as e:
print(f"Error executing file remotely: {str(e)}")
elif command == "exit":
print("Exiting...")
break
else:
print("Invalid command. Use upload, download, execute, or exit.")

def start_client():
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
conn.connect((SERVER_IP, SERVER_PORT))
print(f"Connected to {SERVER_IP}:{SERVER_PORT}")
threading.Thread(target=send_screen, args=(conn,), daemon=True).start()
handle_commands(conn)
except OSError as e:
print(f"Failed to connect to server: {str(e)}")
except Exception as e:
print(f"An unexpected error occurred: {str(e)}")
finally:
try:
conn.close()
print("Connection closed.")
except OSError as e:
print(f"Error closing connection: {str(e)}")

if __name__ == "__main__":
start_client()



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

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

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

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

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

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

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