(您的问题类似于this question(我已适当地将其标记为重复),但为方便起见,这是我的答案的副本!)
有多种方法可以处理此问题;您将选择哪一项取决于您要完成多少工作。*
但首先,您应该(对自己)澄清您是在处理 UDP 还是 TCP; UDP 套接字没有“底层 TCP 堆栈”。此外,UDP 是用于发送整个数据(如文本或照片)的错误协议;它是一个不可靠的协议,因此不能保证您接收到每个数据包,除非您使用托管套接字库(例如 ENet)。
Lua51/LuaJIT + LuaSocket
轮询是唯一的方法。
- 阻塞:调用
socket.select,不带时间参数,等待套接字可读。
- 非阻塞:调用
socket.select,超时参数为0,并在您正在读取的套接字上使用sock:settimeout(0)。
然后简单地重复调用这些。
我建议对非阻塞版本使用coroutine scheduler,以允许程序的其他部分继续执行而不会造成太多延迟。
Lua51/LuaJIT + LuaSocket + Lua Lanes(推荐)
与上述方法相同,但套接字存在于使用Lua Lanes(latest source)创建的另一个通道(另一个线程中的轻量级 Lua 状态)中。这使您可以立即从套接字读取数据并进入缓冲区。然后,您使用linda 将数据发送到主线程进行处理。
这可能是您问题的最佳解决方案。
我已经为此做了一个简单的例子,可以使用here。它依赖于 Lua Lanes 3.4.0 (GitHub repo) 和修补过的 LuaSocket 2.0.2 (source, patch, blog post re' patch)
结果很有希望,但如果你从中派生出我的示例代码,你肯定应该重构它。
LuaJIT + 操作系统特定的套接字
如果你有点自虐,你可以尝试从头开始实现一个套接字库。 LuaJIT's FFI library 使这从纯 Lua 成为可能。 Lua Lanes 对此也很有用。
对于 Windows,我建议查看 William Adam's blog。他在 LuaJIT 和 Windows 开发方面有过一些非常有趣的冒险经历。至于 Linux 等,请查看 C 教程或 LuaSocket 的源代码,并将它们翻译成 LuaJIT FFI 操作。
(如果 API 需要,LuaJIT 支持 callbacks;但是,与从 Lua 轮询到 C 相比,存在显着的性能成本。)
LuaJIT + ENet
ENet 是一个很棒的库。它提供了 TCP 和 UDP 之间的完美组合:需要时可靠,否则不可靠。它还抽象了操作系统特定的细节,就像 LuaSocket 一样。可以使用 Lua API 进行绑定,也可以通过 LuaJIT 的 FFI 直接访问(推荐)。
*双关语无意。