我在Lua中实现套接字,我正在使用的示例代码使用以下方法来保持连接的活动:
while true do
-- handle socket traffic here
socket.sleep(1)
end
循环显然会阻止项目代码的其余部分运行,但如果我退出循环,套接字服务器会立即断言连接已关闭。
那么如何保持套接字同时打开,因为我的其余Lua代码正常运行? (是否有某种后台工作支持?协程可以用于此目的吗?)
答案 0 :(得分:0)
我使用Lua Lanes来启动一个正在执行套接字i / o并在后台运行的线程。
http://kotisivu.dnainternet.net/askok/bin/lanes/
看一下这个答案,它给出了使用Lua Lanes和套接字的信息。
提供的双线程轮询解决方案可能是最可行的,但是,还有关于协同程序的信息。
答案 1 :(得分:0)
(您的问题类似于this question(我已将其严格标记为副本),但为方便起见,这里是我的答案副本!)
有多种方法可以解决这个问题;您将选择哪一个取决于您想要做多少工作。 *
但首先,您应该(自己)澄清您是在处理UDP还是TCP; UDP套接字没有“底层TCP堆栈”。此外,UDP是用于发送诸如文本或照片之类的整个数据的错误协议;它是一个不可靠的协议,因此除非您使用托管套接字库(例如ENet),否则无法保证接收每个数据包。
轮询是唯一的方法。
socket.select
并等待套接字可读。socket.select
的超时参数调用0
,并在您正在阅读的套接字上使用sock:settimeout(0)
。然后简单地反复调用这些。 我建议使用coroutine scheduler作为非阻塞版本,以允许程序的其他部分继续执行而不会造成太多延迟。
与上面的方法相同,但套接字存在于使用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的FFI library使纯粹的Lua成为可能。 Lua Lanes也会对此有用。
对于Windows,我建议您查看William Adam's blog。他在LuaJIT和Windows开发方面有过一些非常有趣的冒险经历。至于Linux和其他内容,请查看C的教程或LuaSocket的源代码,并将它们转换为LuaJIT FFI操作。
(如果API需要,LuaJIT支持callbacks;但是,与从Lua到C的轮询相比,性能成本显着。)
ENet是一个很棒的图书馆。它提供了TCP和UDP之间的完美组合:在需要时可靠,否则不可靠。它还抽象了操作系统特定的细节,就像LuaSocket一样。您可以使用Lua API绑定它,或通过LuaJIT的FFI直接访问它(推荐)。
* Pun无意识。
答案 2 :(得分:0)
其他答案很好,但有点想念这里最重要的一点:
为什么呢?因为多个套接字很常见,所以OS(最着名的是* ix系统)以epoll
函数的形式实现了“多轮询”。
所有高性能网络库(如ZeroMQ)只保留几个线程,并在其中运行。这降低了内存需求,但不会牺牲速度。
所以我的建议是直接连接到OS库,这在Lua中很容易 。您不必自己编写代码 - 快速谷歌搜索带给我this epoll wrapper [1]然后您仍然可以使用协同程序仅从实际拥有某些数据的套接字中读取。
您可能还想查看ZeroMQ library itself。
[1] Neopallium 为ZMQ创建了Lua绑定,所以我认为它是合法的。
答案 3 :(得分:0)
您确实可以使用协程来实现此目的。这就是流行的图书馆Copas所做的。
根据您的使用案例,您可以使用Copas或查看其源代码以了解它是如何做到的。您还可以查看使用Copas的lua-websockets。