🌐

Socket TCP in Python

Connessioni affidabili con garanzia di consegna

⚖️ Differenze rispetto a UDP

Caratteristica UDP TCP
Connessione Nessuna connessione Connessione stabilita prima dello scambio dati
Affidabilità Nessuna garanzia di consegna Consegna garantita e ordinata
Velocità Maggiore Minore per l’overhead
Uso Streaming, gaming Web, trasferimenti file

🖥️ Comandi per il Server TCP

1

Creazione del socket TCP

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  • socket.SOCK_STREAM specifica l’uso di TCP

2

Associazione e ascolto

server.bind(("127.0.0.1", 8080))
server.listen(5)
  • bind() assegna IP e porta
  • listen(5) imposta la coda massima di connessioni in attesa

3

Accettazione di una connessione

conn, addr = server.accept()
print(f"Connessione accettata da {addr}")

4

Ricezione e invio di dati

data = conn.recv(1024).decode()
print("Messaggio ricevuto:", data)
conn.send("Risposta dal server".encode())

5

Chiusura del socket

conn.close()
server.close()

💻 Comandi per il Client TCP

1

Creazione del socket TCP

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

2

Connessione al server

client.connect(("127.0.0.1", 8080))

3

Invio di un messaggio

client.send("Ciao server TCP!".encode())

4

Ricezione della risposta

data = client.recv(1024).decode()
print("Risposta dal server:", data)

5

Chiusura del socket

client.close()

💡 Esempi Base

Server TCP Base

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("127.0.0.1", 8080))
server.listen(5)
print("Server in ascolto...")

conn, addr = server.accept()
print(f"Connessione da {addr}")

data = conn.recv(1024).decode()
print("Dati ricevuti:", data)

conn.send("Messaggio ricevuto".encode())

conn.close()
server.close()

Client TCP Base

import socket

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(("127.0.0.1", 8080))
print("Connesso al server")

client.send("Ciao server!".encode())

response = client.recv(1024).decode()
print("Risposta:", response)

client.close()

🔹 Uso di with

L’uso di with in Python è fondamentale per la gestione automatica delle risorse, garantendo che il socket venga chiuso correttamente anche in caso di errori.

Perché usare with?

  • Previene porte bloccate: chiude automaticamente il socket
  • Gestione delle eccezioni: rilascia risorse anche in caso di errore
  • Codice più pulito: non serve chiamare esplicitamente close()

Server con with

import socket

HOST = '127.0.0.1'
PORT = 65432

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    print(f"Server su {HOST}:{PORT}")
    
    conn, addr = s.accept()
    with conn:
        print(f"Connesso da {addr}")
        while True:
            data = conn.recv(1024)
            if not data:
                break
            print(f"Ricevuto: {data.decode()}")
            conn.sendall(data)

Client con with

import socket

HOST = '127.0.0.1'
PORT = 65432

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))
    s.sendall(b'Hello, Server!')
    data = s.recv(1024)

print(f"Risposta: {data.decode()}")

🚀 Progetti Avanzati

🔐 Server di Login e Registrazione

Server che gestisce autenticazione utenti con dizionario username/password.

import socket

users = {
    "alice": "password123",
    "bob": "qwerty",
    "pako": "abcd1234"
}

def client_funz(conn):
    conn.sendall(b"Benvenuto! Digita LOGIN, REGISTER o DELETE:\n")
    
    while True:
        scelta = conn.recv(1024).decode().strip().upper()

        if scelta == "LOGIN":
            conn.sendall(b"Username e password separati da spazio:\n")
            data = conn.recv(1024).decode().strip().split()

            if len(data) == 2:
                username, password = data
                if username in users and users[username] == password:
                    conn.sendall(b"Accesso riuscito\n")
                    break
                else:
                    conn.sendall(b"Accesso negato. Riprova:\n")
            else:
                conn.sendall(b"Formato errato. Usa: username password\n")

        elif scelta == "REGISTER":
            conn.sendall(b"Nuovo username e password:\n")
            data = conn.recv(1024).decode().strip().split()

            if len(data) == 2:
                username, password = data
                if username not in users:
                    users[username] = password
                    conn.sendall(b"Registrazione completata\n")
                    break
                else:
                    conn.sendall(b"Utente esistente. Riprova:\n")
        
        elif scelta == "DELETE":
            conn.sendall(b"Username e password per cancellazione:\n")
            data = conn.recv(1024).decode().strip().split()

            if len(data) == 2:
                username, password = data
                if username in users and users[username] == password:
                    del users[username]
                    conn.sendall(b"Utente eliminato\n")
                    break

    conn.close()

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("127.0.0.1", 65432))
server.listen()
print("Server in ascolto...")

while True:
    conn, addr = server.accept()
    client_funz(conn)

import socket

def client_program():
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect(("127.0.0.1", 65432))

    while True:
        message = client.recv(1024).decode()
        print(message)

        if "Accesso riuscito" in message or "Utente eliminato" in message or "Registrazione completata" in message:
            break

        risp = input("> ")
        client.sendall(risp.encode())

    client.close()

if __name__ == "__main__":
    client_program()

📁 File Transfer Client-Server

Sistema per trasferire file tra dipendenti senza email o cloud.

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("127.0.0.1", 65432))
server.listen()

while True:
    conn, addr = server.accept()
    filename = conn.recv(1024).decode()
    
    with open(filename, "wb") as f:
        while True:
            data = conn.recv(1024)
            if not data:
                break
            f.write(data)
    
    conn.close()

Client

import socket

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(("127.0.0.1", 65432))

filename = "documento.txt"
client.sendall(filename.encode())

with open(filename, "rb") as f:
    data = f.read(1024)
    while data:
        client.sendall(data)
        data = f.read(1024)

client.close()

🎯 Esercitazione

Obiettivo: Creare un semplice servizio di chat tra client e server.

  • Modificare il codice in modo che il server possa gestire più client contemporaneamente
  • Implementare un meccanismo per terminare la connessione in modo pulito
  • Permettere ai client di inviare più messaggi senza dover riavviare la connessione

🚀 Altre Lezioni

Continua il tuo percorso sui socket in Python

📚 Percorso Formativo

Completa il tuo percorso sui socket in Python

Torna in alto