Ci sono vari modi di gestire questo problema; quale sceglierai dipende da quanto lavoro vuoi fare. *
Ma prima, è necessario chiarire (a se stessi) se si ha a che fare con UDP o TCP; non esiste uno "stack TCP sottostante" per i socket UDP. Inoltre, UDP è il protocollo sbagliato da utilizzare per inviare interi dati come un testo o una foto; si tratta di un protocollo inaffidabile, pertanto non si garantisce la ricezione di tutti i pacchetti, a meno che non si utilizzi una libreria socket gestita (come ENet).
Lua51/LuaJIT + LuaSocket
Polling è l'unico metodo.
- Blocco: chiamare
socket.select
senza argomento orario e attendere che il socket sia leggibile.
- Non bloccante: chiamare
socket.select
con un argomento di timeout di 0
e utilizzare sock:settimeout(0)
sul socket da cui si sta leggendo.
Quindi chiamarli ripetutamente. Suggerirei di utilizzare un coroutine scheduler per la versione non bloccante, per consentire ad altre parti del programma di continuare l'esecuzione senza causare troppo ritardo.
Lua51/LuaJIT + LuaSocket + Lua Lanes (positiva)
Uguale al metodo di cui sopra, ma la presa esiste in un'altra corsia (un peso leggero stato Lua in un altro thread) effettuata utilizzando Lua Lanes (latest source). Ciò consente di leggere immediatamente i dati dal socket e in un buffer. Quindi, si utilizza un linda per inviare i dati al thread principale per l'elaborazione.
Questa è probabilmente la soluzione migliore per il tuo problema.
Ho fatto un semplice esempio di questo, disponibile here. Esso si basa su Lua Lanes 3.4.0 (GitHub repo) e un LuaSocket patch 2.0.2 (source, patch, blog post re' patch)
I risultati sono promettenti, anche se si dovrebbe assolutamente refactoring il mio codice di esempio, se si deriva da esso.
LuaJIT + specifici del sistema operativo prese
Se sei un po 'masochista, si può provare l'attuazione di una libreria presa da zero. FFI library di LuaJIT rende questo possibile dalla pura Lua. Lua Lanes sarebbe utile anche per questo.
Per Windows, suggerisco di dare un'occhiata a William Adam's blog. Ha avuto avventure molto interessanti con lo sviluppo di LuaJIT e Windows. Per quanto riguarda Linux e il resto, guarda i tutorial per C o la fonte di LuaSocket e traducili in operazioni LuaJIT FFI.
(LuaJIT supporta callbacks se l'API lo richiede, tuttavia, v'è un costo delle prestazioni signficant rispetto al polling da Lua a C.)
LuaJIT + ENet
ENet è una grande biblioteca. Fornisce il perfetto mix tra TCP e UDP: affidabile quando desiderato, altrimenti inaffidabile. Estrae anche dettagli specifici del sistema operativo, proprio come fa LuaSocket. È possibile utilizzare l'API Lua per collegarlo o accedervi direttamente tramite FFI di LuaJIT (consigliato).
* Punzo involontario.
Mi rendo conto che Lua è effettivamente un sistema a thread singolo con eventi di sistema che utilizzano i callback. Speravo solo di ricevere una chiamata quando ci sono dati disponibili invece di continuare a guardarli. – user4749
Dovresti comunque trasferire il controllo a chiunque stia facendo la richiamata per ricevere la richiamata. Quindi ogni volta che lo faresti, controlla se i dati sono lì. –
Non sono d'accordo molto. L'uso di lua-ev o di un altro evento NON impone il polling!Usando Lua + "Some Event Loop" viene utilizzato in modo altamente produttivo in dispositivi embedded (dove node.js è troppo grande) per attività serie con prestazioni molto buone e basso footprint. Per alcune situazioni questa è una corrispondenza perfetta. Ci sono moduli attorno ai quali è molto facile lavorare con il sistema operativo su un livello molto basso (https://github.com/justincormack/ljsyscall). – lipp