I\'m working on a little Lua app (under Lua for Windows, if that matters) that uses sockets to communicate with the outside world. (LuaSocket)
And I\'m trying to mak
Lua Lanes creates an entirely new (but minimal) Lua state for each lane. Any upvalues or arguments passed are copied, not referenced; this means your allClients table is being copied, along with the sockets it contains.
The error is occurring because the sockets are userdata, which Lua Lanes does not know how to copy without some advice from a C module. Unfortunately, LuaSocket offers no such advice. (There are ways around this, but be cautious: LuaSocket is not thread-safe and synchronisation bugs are very difficult to track down.)
Although it will not solve your problem, you should note that you need to require LuaSocket in your spawned lane; it is not copied by default.
These are ordered from easy to hard (and mostly transcribed from my other answer here).
Repeatedly call polling functions in LuaSocket:
socket.select
with no time argument and wait for the socket to be readable.socket.select
with a timeout argument of 0
, and use sock:settimeout(0)
on the socket you're reading from.Simply call these repeatedly. I would suggest using a coroutine scheduler for the non-blocking version, to allow other parts of the program to continue executing without causing too much delay.
(If you go for this solution, I suggest reviewing Paul's answer.)
Your main thread does not deal with sockets at all. Instead, it spawns another lane which requires LuaSocket, handles all clients and communicates with the main thread via a linda.
This is probably the most viable option for you.
Same as above, except each thread handles a subset of all the clients (1 to 1 is possible, but diminishing return will set in with large quantities of clients).
I've made a simple example of this, available here. It relies on Lua Lanes 3.4.0 (GitHub repo) and a patched LuaSocket 2.0.2 (source, patch, blog post re' patch)
The results are promising, though you should definitely refactor my example code if you derive from it.
ENet is a great library. It provides the perfect mix between TCP and UDP: reliable when desired, unreliable otherwise. It also abstracts operating system specific details, much like LuaSocket does. You can use the Lua API to bind it, or directly access it via LuaJIT's FFI (recommended).
Programming Lua has example on non-preemptive multithreading (using coroutines), which you can probably use almost directly. In my opinion coroutines will be a better solution for your use case.
There is also copas library that describes itself as "a dispatcher based on coroutines that can be used by TCP/IP servers", but you can actually use it for sending requests asynchronously too (using a combination of addthread
and step
calls).