Lua套接字-异步事件

问题描述:

在当前的lua套接字实现中,我看到我们必须安装一个定期回调的计时器,以便我们检入非阻塞API以查看是否收到了任何东西.

In current lua sockets implementation, I see that we have to install a timer that calls back periodically so that we check in a non blocking API to see if we have received anything.

这一切都很好,但是在UDP情况下,如果发件人发送了很多信息,我们是否有丢失数据的风险.假设另一台设备通过UDP发送2MB的照片,我们检查套接字每100毫秒接收一次.在我们的调用查询基础TCP堆栈之前,基础系统必须以2MBps的速度存储200Kbit.

This is all good and well however in UDP case, if the sender has a lot of info being sent, do we risk loosing the data. Say another device sends a 2MB photo via UDP and we check socket receive every 100msec. At 2MBps, the underlying system must store 200Kbits before our call queries the underlying TCP stack.

当我们在特定的套接字上接收数据时,是否有一种方法可以引发事件,而不是我们现在必须进行的轮询?

Is there a way to get an event fired when we receive the data on the particular socket instead of the polling we have to do now?

有多种方法可以解决此问题;您将选择哪一个取决于您要完成的工作. *

There are a various ways of handling this issue; which one you will select depends on how much work you want to do.*

但是首先,您应该(自己)弄清楚要处理的是UDP还是TCP. UDP套接字没有底层TCP堆栈".同样,UDP是用于发送诸如文本或照片之类的整个数据的错误协议.这是一种不可靠的协议,因此除非您使用的是托管套接字库(例如 ENet ).

But first, you should clarify (to yourself) whether you are dealing with UDP or TCP; there is no "underlying TCP stack" for UDP sockets. Also, UDP is the wrong protocol to use for sending whole data such as a text, or a photo; it is an unreliable protocol so you aren't guaranteed to receive every packet, unless you're using a managed socket library (such as ENet).

投票是唯一的方法.

  • 阻塞:不带任何时间参数调用socket.select,并等待套接字可读.
  • 无阻塞:使用0的超时参数调用socket.select,并在要读取的套接字上使用sock:settimeout(0).
  • Blocking: call socket.select with no time argument and wait for the socket to be readable.
  • Non-blocking: call socket.select with a timeout argument of 0, and use sock:settimeout(0) on the socket you're reading from.

然后简单地反复调用这些. 我建议对非阻塞版本使用协程调度程序,以允许程序的其他部分继续运行执行而不会造成太多延迟.

Then 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.

与上述方法相同,但是套接字位于使用 Lua Lanes (最新消息).这使您可以立即从套接字读取数据并将其读入缓冲区.然后,您使用 linda 将数据发送到主线程进行处理

Same as the above method, but the socket exists in another lane (a lightweight Lua state in another thread) made using Lua Lanes (latest source). This allows you to instantly read the data from the socket and into a buffer. Then, you use a linda to send the data to the main thread for processing.

这可能是解决您问题的最佳方法.

This is probably the best solution to your problem.

我已经提供了一个简单的示例,可以在此处获得.它依赖于Lua Lanes 3.4.0( GitHub存储库)和修补的LuaSocket 2.0.2(博客发布相关补丁)

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.

如果您有点受虐狂,则可以尝试从头开始实现套接字库. LuaJIT

If you're a little masochistic, you can try implementing a socket library from scratch. LuaJIT's FFI library makes this possible from pure Lua. Lua Lanes would be useful for this as well.

对于Windows,我建议您看一下威廉·亚当的博客.他在LuaJIT和Windows开发方面经历了一些非常有趣的冒险.至于Linux及其它其余部分,请查看C教程或LuaSocket的源代码,并将其转换为LuaJIT FFI操作.

For Windows, I suggest taking a look at William Adam's blog. He's had some very interesting adventures with LuaJIT and Windows development. As for Linux and the rest, look at tutorials for C or the source of LuaSocket and translate them to LuaJIT FFI operations.

(如果API要求,LuaJIT支持回调;但是,这会显着降低性能成本相比于从Lua到C的轮询.)

(LuaJIT supports callbacks if the API requires it; however, there is a signficant performance cost compared to polling from Lua to C.)

ENet 是一个很棒的库.它提供了TCP和UDP之间的完美结合:需要时可靠,否则不可靠.它还像LuaSocket一样抽象了特定于操作系统的详细信息.您可以使用Lua API进行绑定,也可以通过LuaJIT的FFI直接访问它(推荐).

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).

* 无意打扰.

* Pun unintentional.