Lua sockets - Événements Asynchrones
En courant lua mise en œuvre des sockets, je vois que nous avons installer un timer qui appelle régulièrement, de sorte que l'on contrôle non bloquant API pour voir si nous avons rien reçu.
C'est tout bon et bien cependant en UDP cas, si l'expéditeur a beaucoup d'info envoyé, ne risquons-nous pas de perdre des données. Dire d'un autre appareil envoie une photo de 2 mo via UDP et nous vérifions socket recevoir chaque 100msec. À 2MBps, le système sous-jacent doit stocker 200Kbits avant notre appel interroge le sous-jacent pile TCP.
Est-il un moyen d'obtenir un événement lancé quand nous recevons les données sur la socket particulier au lieu de l'interrogation que nous avons à faire maintenant?
Vous devez vous connecter pour publier un commentaire.
Il y a différentes façons de traiter de cette question; laquelle vous sélectionnez dépend de la quantité de travail que vous voulez faire.*
Mais d'abord, vous devez préciser (pour vous) si vous faites affaire avec le protocole TCP ou UDP; il n'y a pas de "sous-jacent pile TCP" pour les sockets UDP. Aussi, UDP est le mauvais protocole à utiliser pour l'envoi de l'ensemble des données telles qu'un texte ou une photo; c'est un protocole non fiable de sorte que vous êtes assuré de recevoir tous les paquets, sauf si vous utilisez un gérés bibliothèque de socket (comme ENet).
Lua51/LuaJIT + LuaSocket
Interrogation est la seule méthode.
socket.select
avec aucun argument de temps et d'attendre que le support soit lisible.socket.select
avec un délai d'attente argument de0
, et l'utilisationsock:settimeout(0)
sur le support que vous êtes en train de lire à partir d'.Puis il suffit de les appeler à plusieurs reprises.
Je voudrais suggérer à l'aide d'un coroutine planificateur pour le non-blocage de version, pour permettre à d'autres parties du programme à poursuivre l'exécution sans causer trop de retard.
Lua51/LuaJIT + LuaSocket + Lua Voies (Recommandé)
Même que la méthode ci-dessus, mais le support existe dans une autre voie (un léger Lua état dans un autre thread) en utilisant Lua Voies (dernière source). Cela vous permet de lire instantanément les données de la prise de courant et dans une mémoire tampon. Ensuite, vous utilisez un linda pour envoyer les données vers le thread principal pour le traitement.
C'est probablement la meilleure solution à votre problème.
J'ai fait un exemple simple de cette, disponible ici. Il s'appuie sur Lua Voies 3.4.0 (Dépôt GitHub) et une version patchée de LuaSocket 2.0.2 (source, patch, blog re' patch)
Les résultats sont prometteurs, bien que vous devriez certainement refactoriser mon exemple de code si vous en découlent.
LuaJIT + OS sockets
Si vous êtes un peu maso, vous pouvez essayer de mettre en œuvre une bibliothèque de socket à partir de zéro. LuaJIT's FFI de la bibliothèque de ce fait possible de pure Lua. Lua Voies serait utile pour cela.
Pour Windows, je suggère de prendre un coup d'oeil à William Adam blog. Il avait quelques très intéressant aventures avec LuaJIT et de développement de Windows. Comme pour Linux et le reste, regardez des tutoriels de C ou de la source de LuaSocket et de les traduire en LuaJIT FFI opérations.
(LuaJIT prend en charge rappels si l'API exige; cependant, il est un des importants sur les performances par rapport à une interrogation de Lua pour C.)
LuaJIT + ENet
ENet est une grande bibliothèque. Il propose un mélange parfait entre TCP et UDP: fiable lorsque vous le souhaitez, peu fiables autrement. Il a également résumés système d'exploitation de plus de détails, un peu comme LuaSocket n'. Vous pouvez utiliser l'API Lua pour le lier, ou accéder directement via LuaJIT du FFI (recommandé).
* jeu de mots involontaire.
- Je utiliser lua-ev https://github.com/brimworks/lua-ev pour toutes les e /s-multiplexage des trucs.
Il est très facile à utiliser, s'adapte en Lua (et ses
function
) comme un charme. C'est soit select/poll/epoll ou kqueue base et fonctionne très bien aussi.À mon avis Lua+luasocket+lua-ev est juste une équipe de rêve pour la construction efficace et robuste applications de mise en réseau (pour les périphériques intégrés/environnement). Il y a des outils plus puissants là-bas! Mais si vos ressources sont limitées, Lua est un bon choix!
Lua est intrinsèquement single-threaded; il n'y a pas une telle chose comme un "événement". Il n'existe aucun moyen d'interrompre l'exécution de code Lua. Ainsi, alors que vous pourriez monter quelque chose qui ressemblait à un événement, vous ne jamais obtenir un si vous appelez une fonction qui a interrogé les événements qui étaient disponibles.
Généralement, si vous essayez d'utiliser Lua pour ce genre de bas niveau de travail, vous utilisez le mauvais outil. Vous devriez être à l'aide de C ou quelque chose d'accéder à ce type de données, puis de le passer à Lua quand il est prêt.
Vous êtes probablement en utilisant un non-bloquant
select()
à "interroger" les sockets pour toutes les nouvelles données disponibles. Luasocket ne pas fournir toute autre interface pour voir si il y a de nouvelles données disponibles (pour autant que je sache), mais si vous craignez que cela prend trop de temps quand vous faites cela 10 fois par seconde, envisager la rédaction d'une version simplifiée qui vérifie uniquement d'une prise secteur dont vous avez besoin et évite de créer et de jeter Lua tables. Si ce n'est pas une option, envisager l'adoption d'nil
àselect()
au lieu de{}
pour ces listes, vous n'avez pas besoin de lire et passer des tableaux statiques au lieu de celles de nature temporaire:au lieu de