在当前的 lua 套接字实现中,我看到我们必须安装一个定期回调的计时器,以便我们检查非阻塞 API 以查看我们是否收到任何内容。
这一切都很好,但是在 UDP 情况下,如果发送者有很多信息正在发送,我们是否有丢失数据的风险。假设另一台设备通过 UDP 发送 2MB 照片,我们每 100 毫秒检查一次套接字接收。在 2MBps 时,在我们的调用查询底层 TCP 堆栈之前,底层系统必须存储 200Kbits。
当我们在特定套接字上接收到数据而不是我们现在必须做的轮询时,有没有办法让事件触发?
最佳答案
有多种方法可以处理此问题;你会选择哪一个取决于你想做多少工作。*
但首先,您应该(对自己)澄清您是在处理 UDP 还是 TCP; UDP 套接字没有“底层 TCP 堆栈”。此外,UDP 是用于发送整个数据(如文本或照片)的错误协议(protocol);它是一个不可靠的协议(protocol),因此不能保证您接收到每个数据包,除非您使用托管套接字库(例如 ENet )。
Lua51/LuaJIT + LuaSocket
轮询是唯一的方法。
socket.select
没有时间参数并等待套接字可读。 socket.select
超时参数为 0
, 并使用 sock:settimeout(0)
在您正在读取的套接字上。 然后简单地重复调用这些。
我建议使用 coroutine scheduler对于非阻塞版本,允许程序的其他部分继续执行而不会造成太多延迟。
Lua51/LuaJIT + LuaSocket + Lua Lanes (受到推崇的)
与上述方法相同,但套接字存在于使用 Lua Lanes 制作的另一个 channel 中(另一个线程中的轻量级 Lua 状态) (latest source)。这使您可以立即从套接字读取数据并进入缓冲区。然后,您使用 linda将数据发送到主线程进行处理。
这可能是您问题的最佳解决方案。
我做了一个简单的例子,可用 here .它依赖于 Lua Lanes 3.4.0 ( GitHub repo ) 和修补的 LuaSocket 2.0.2 ( source , patch , blog post re' patch )
结果是有希望的,但如果你从中派生出我的示例代码,你肯定应该重构它。
LuaJIT + 操作系统特定的套接字
如果你有点自虐,你可以尝试从头实现一个套接字库。 LuaJIT的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 来绑定(bind)它,或者直接通过 LuaJIT 的 FFI 访问它(推荐)。
* 双关语无意。
关于sockets - Lua 套接字 - 异步事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12889361/