0Pricing
Lua Academy · Lezione

Costruire un client

Richieda dati a un server.

Costruire un client è una lezione Lua Academy gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Lua Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Lua Academy include 4 lezioni in totale.

Ciclo di vita del client

Un client TCP segue un ciclo di vita chiaro: crea un socket, si connette a un server, scambia dati e infine chiude la connessione.

In LuaSocket ogni passaggio corrisponde a una chiamata di metodo, e ognuna può fallire. Un client ben scritto controlla ogni valore restituito e chiude il proprio socket lungo qualsiasi percorso di errore.

local socket = require("socket")
local client = assert(socket.tcp())

Connettersi in sicurezza

Imposti un timeout di connessione prima di chiamare connect, così un host non raggiungibile non bloccherà il programma. In genere bastano pochi secondi.

Se connect restituisce nil, registri l'errore e interrompa l'esecuzione. Non presuma mai che l'handshake sia riuscito.

client:settimeout(5)
local ok, err = client:connect("127.0.0.1", 8080)
if not ok then
  client:close()
  error("connect failed: " .. err)
end

Usare socket.connect

Nel caso più comune, socket.connect(host, port) racchiude la creazione e la connessione. Restituisce un oggetto client pronto oppure nil e un errore.

Questa forma è concisa, ma non consente di impostare un timeout prima dell'handshake; pertanto, sulle reti inaffidabili, preferisca la forma esplicita.

local socket = require("socket")
local client, err = socket.connect("example.com", 13)
if not client then error(err) end

Inviare una richiesta

Una volta connesso, scriva i byte della richiesta con send. Molti protocolli testuali delimitano le righe con ritorno a capo + nuova riga (\r\n).

Poiché TCP è un flusso, termini chiaramente ogni messaggio logico, in modo che il server sappia dove finisce.

local msg = "PING\r\n"
local sent, err = client:send(msg)
if not sent then error("send failed: " .. err) end

Leggere una risposta riga per riga

Per i protocolli basati su righe, esegua un ciclo di lettura usando il pattern "*l". Ogni chiamata restituisce una riga senza il relativo terminatore.

In caso di nil, analizzi l'errore: "closed" indica che il server ha chiuso la connessione, mentre "timeout" indica che non sono arrivati dati in tempo.

client:settimeout(5)
local line, err = client:receive("*l")
if line then
  print("server said:", line)
else
  print("recv error:", err)
end

Leggere una risposta completa

I protocolli richiesta/risposta spesso leggono tutto finché il server non chiude la connessione. Usi "*a" per acquisire l'intero corpo.

Se chiude prima il lato di invio con shutdown("send"), il server rileva la fine dell'input e può completare la risposta.

client:send("GET DATA\r\n")
client:shutdown("send")
local body, err = client:receive("*a")
print(#(body or ""), "bytes received")

Framing a lunghezza fissa

I protocolli binari spesso antepongono a ogni messaggio la sua lunghezza. Legga prima l'intestazione della lunghezza, poi legga esattamente quel numero di byte.

Passare un numero a receive blocca l'esecuzione finché non arriva quel numero di byte o il socket non segnala un errore, fornendo un framing preciso sul flusso di byte.

local header = client:receive(4)
local len = string.unpack(">I4", header)
local payload = client:receive(len)

Un client echo completo

Ecco il flusso completo: connettersi, inviare una riga, leggere la riga restituita e chiudere la connessione. Questa è la struttura tipica di un client LuaSocket.

Noti che, per brevità, ogni chiamata soggetta a errori è protetta con assert, ma un client reale gestirebbe gli errori in modo appropriato.

local socket = require("socket")
local c = assert(socket.connect("127.0.0.1", 8080))
assert(c:send("hello\r\n"))
print(c:receive("*l"))
c:close()

Gestire le disconnessioni

I server possono interrompere le connessioni in qualsiasi momento. Un send verso un peer chiuso può restituire nil, "closed", mentre receive restituisce i dati parziali insieme all'errore.

Tratti "closed" come un normale stato terminale, non come un arresto anomalo. La logica di riconnessione deve trovarsi in un wrapper di retry attorno al client.

local data, err, partial = client:receive("*a")
if err == "closed" then
  print("peer closed, got", #partial, "bytes")
end

Client non bloccanti

Imposti il timeout su 0 per ottenere un client completamente non bloccante. Le chiamate restituiscono quindi immediatamente il controllo e segnalano "timeout" quando non è possibile fare progressi.

Combini questa configurazione con socket.select per attendere in modo efficiente la disponibilità di molti socket senza eseguire cicli intensivi.

client:settimeout(0)
local r = socket.select({client}, nil, 5)
if #r > 0 then print(client:receive("*l")) end

Risoluzione dei nomi host

Se si connette usando un nome host, LuaSocket lo risolve automaticamente. Per esaminare o memorizzare nella cache la risoluzione, chiami direttamente socket.dns.toip o socket.dns.getaddrinfo.

Risolvere il nome una sola volta e connettersi tramite IP evita ricerche DNS ripetute in un ciclo serrato di riconnessione.

local socket = require("socket")
local ip = assert(socket.dns.toip("example.com"))
local c = assert(socket.connect(ip, 80))

Verifica rapida

Scelga il modo corretto per leggere tutto ciò che un server invia finché non chiude la connessione.

Riepilogo

Ha costruito un client TCP dall'inizio alla fine: connettersi con un timeout, definire il framing e inviare le richieste, leggere risposte basate su righe, sul conteggio dei byte o sull'intero flusso, e chiudere correttamente.

Ha inoltre visto come gestire le disconnessioni, la modalità non bloccante con select e la memorizzazione nella cache del DNS. Ora scriverà il lato server che risponde a questi client.

Domande Frequenti

La lezione «Costruire un client» è gratuita?

Sì — il testo completo di «Costruire un client» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Lua Academy, passa a CoddyKit PRO. Il corso Lua Academy include 4 lezioni in totale.

Cosa imparerò in «Costruire un client»?

Richieda dati a un server. Eserciti Lua Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Lua Academy?

Non è richiesta alcuna esperienza precedente. Lua Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.

Quanto tempo richiede la lezione «Costruire un client»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Lua Academy?

Sì. Ogni lezione Lua Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Fondamenti di TCP
  2. Costruire un client
  3. Costruire un server
  4. Richieste HTTP
← Torna a Lua Academy