这一切都很好,但在UDP情况下,如果发件人发送了大量信息,我们是否有丢失数据的风险.假设另一台设备通过UDP发送2MB照片,我们每100毫秒检查一次套接字.在2MBps时,底层系统必须在我们的调用查询底层TCP堆栈之前存储200Kbits.
当我们收到特定套接字上的数据而不是我们现在要做的轮询时,有没有办法让事件被触发?
有各种方法来处理这个问题;您将选择哪一个取决于您想要做多少工作.*但首先,您应该(自己)澄清您是在处理UDP还是TCP; UDP套接字没有“底层TCP堆栈”.此外,UDP是用于发送诸如文本或照片之类的整个数据的错误协议;它是一个不可靠的协议,因此除非您使用托管套接字库(例如ENet),否则无法保证每个数据包都会收到.
Lua51 / LuaJIT LuaSocket
轮询是唯一的方法.
>阻塞:调用没有时间参数的socket.select并等待套接字可读.
>非阻塞:使用超时参数0调用socket.select,并在您正在读取的套接字上使用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的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直接访问它(推荐).
*双关语无意识.