Script di Chat Server e Client in Python

Gli script Server e Client forniti implementano una chat di base utilizzando Python, con caratteristiche di sicurezza attraverso la crittografia. Il Server gestisce connessioni multiple attraverso il multithreading, mentre il Client permette agli utenti di inviare e ricevere messaggi.

Script Server

import socket
import threading
from cryptography.fernet import Fernet
from configvar import ipaddress

ipserver = ipaddress
clienti = []
id_counter = 1  # Contatore per gli ID utente

def gestisci_client(conn, id_utente, cifra):
    while True:
        try:
            # Ricevere messaggio dal client corrente
            messaggio_cifrato = conn.recv(1024)
            messaggio = cifra.decrypt(messaggio_cifrato).decode()

            # Inoltrare il messaggio a tutti gli altri client
            for cliente in clienti:
                if cliente != conn:
                    messaggio_cifrato = cifra.encrypt(messaggio.encode())
                    cliente.send(messaggio_cifrato)

        except:
            # Rimuovere il client disconnesso dalla lista dei clienti
            clienti.remove(conn)
            conn.close()
            break

# Generare una chiave segreta per la crittografia
chiave = Fernet.generate_key()
cifra = Fernet(chiave)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((f"{ipserver}", 12345))
s.listen(5)

print(f"Ascoltando... Chiave segreta: {chiave.decode()}")

while True:
    conn, addr = s.accept()
    print(f"Connesso a {addr}")

    clienti.append(conn)

    # Assegna un ID unico al nuovo client e incrementa il contatore
    id_utente = id_counter
    id_counter += 1

    messaggio_id_utente = f"ID_UTENTE:{id_utente}"
    messaggio_cifrato = cifra.encrypt(messaggio_id_utente.encode())
    conn.send(messaggio_cifrato)

    thread = threading.Thread(target=gestisci_client, args=(conn, id_utente, cifra))
    thread.start()

Script Client

import socket
import threading
from cryptography.fernet import Fernet
from configvar import ipaddress

ipserver = ipaddress

# Inizializza il numero dell'utente come None (o un altro valore simbolico)
numero_utente = None

def gestisci_server(s, cifra):
    global numero_utente
    while True:
        try:
            messaggio_cifrato = s.recv(1024)
            if not messaggio_cifrato:
                print("Server disconnesso")
                break
            messaggio = cifra.decrypt(messaggio_cifrato).decode()

            if messaggio.startswith("ID_UTENTE:"):
                numero_utente = int(messaggio.split(":")[1])
                print(f"Sono la Persona {numero_utente}")
                continue

            print(f"\nPersona : {messaggio}")
            if numero_utente is not None:
                print(f"Persona {numero_utente}: ", end="", flush=True)
            else:
                print("Aspettando l'ID utente dal server...", end="", flush=True)
        except Exception as e:
            print(f"Errore: {e}")
            break

chiave = input("Inserire la chiave segreta: ").encode()
cifra = Fernet(chiave)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((f"{ipserver}", 12345))

# Prima ricezione dell'ID utente dal server
if numero_utente is not None:
    print(f"Persona {numero_utente}: ", end="", flush=True)
else:
    print("Aspettando l'ID utente dal server...", end="", flush=True)

thread_ricezione = threading.Thread(target=gestisci_server, args=(s, cifra))
thread_ricezione.start()

while True:
    try:
        messaggio_da_inviare = input()
        if numero_utente is not None:
            messaggio_cifrato = cifra.encrypt(messaggio_da_inviare.encode())
            s.send(messaggio_cifrato)
            print(f"Persona {numero_utente}: ", end="", flush=True)
    except Exception as e:
        print(f"Errore: {e}")
        break

Struttura e Funzionalità

Server:

  • Gestione Multi-Client: Utilizza socket e threading per gestire connessioni multiple simultanee.
  • Crittografia: Impiega cryptography.fernet per crittografare i messaggi tra client e server.
  • Ricezione e Inoltro Messaggi: Decodifica i messaggi ricevuti e li inoltra agli altri client connessi.

Client:

  • Connessione al Server: Si connette al server e gestisce la ricezione dei messaggi.
  • Decodifica e Invio Messaggi: Decodifica i messaggi ricevuti e permette agli utenti di inviare messaggi crittografati.
  • Gestione ID Utente: Assegna e visualizza un ID unico per ogni utente.

Valutazione Tecnica

Sicurezza: La crittografia Fernet è un punto di forza per la sicurezza dei messaggi.

Robustezza: La gestione delle eccezioni nel client e nel server aumenta la robustezza dello script. Tuttavia, potrebbero esserci miglioramenti nell’handling di errori specifici.

Usabilità: L’assegnazione degli ID utente e la visualizzazione chiara dei messaggi contribuiscono a una buona esperienza utente.

Estensibilità e Manutenibilità: La struttura modulare facilita l’aggiunta di nuove funzionalità o modifiche.

Performance: Il multithreading è ben gestito, ma la scalabilità potrebbe essere un problema con un numero elevato di clienti contemporanei.

Conclusioni

Gli script sono un ottimo esempio di come creare una chat di base con funzionalità di sicurezza in Python. Offrono una base solida per futuri sviluppi e miglioramenti.