Lua 卢阿兰和卢阿索克

Lua 卢阿兰和卢阿索克,lua,luasocket,lua-lanes,Lua,Luasocket,Lua Lanes,我正在开发一个小型Lua应用程序(在Lua for Windows下,如果有必要的话),它使用套接字与外部世界进行通信。(LuaSocket) 我试图同时提出几个请求。所以我认为卢阿兰是最好的选择。(当然,如果有更好的解决方案,我愿意接受其他选择,但我不愿意为此处理协同路由。) 大概是这样的: server = assert (socket.bind ('*', 1234)) client = server : accept () -- set id to some unique value a

我正在开发一个小型Lua应用程序(在Lua for Windows下,如果有必要的话),它使用套接字与外部世界进行通信。(LuaSocket)

我试图同时提出几个请求。所以我认为卢阿兰是最好的选择。(当然,如果有更好的解决方案,我愿意接受其他选择,但我不愿意为此处理协同路由。)

大概是这样的:

server = assert (socket.bind ('*', 1234))
client = server : accept ()
-- set id to some unique value
allClients [id] = client
theLane = lanes.gen ("", laneTest) ( id )
print (theLane [1])
其中
laneTest
功能定义如下:

function laneTest (id)
    local client = allClients [id]
    print ('peer: ', client:getpeername())
end
我的问题是,在
laneTest
函数中,当作为车道运行时,我收到以下可爱的错误消息:

尝试索引本地“客户端”(userdata值)

(从行
客户端:getpeername()

所以。。我不确定这是怎么回事?通道与套接字不兼容,还是我做错了什么

我想可能是luaforwindows附带的lanes版本很古老(),不适用于sockets,但最新版本可能会吗?(车道2.0.4与最近的3.xx相比)

我真的不知道如何去更新我的车道版本,否则我现在已经尝试过了,所以。如果这是我的方向,或者有更明显的事情我做错了,我将非常感谢任何建议

编辑: 我通过Luarock安装了lanes,使用lanes 3.1.6-1安装为rock时遇到了同样的问题

编辑2: 尝试此操作(但仍然失败):

  • 声明失败:
    尝试调用全局“require”(零值)
  • 删除函数中的
    require('socket')
    行并重试也会失败,原因是:
    尝试索引本地“client”(用户数据值)
  • 我为错过了显而易见的事情提前道歉,但是。。。如何让插座与通道一起工作

    编辑3:

    好吧,我在中编辑此内容以备将来参考:)

    据我所知,如果不修补luasockets,就无法使用带插槽的通道。更多信息请参见讨论;但简而言之(正如Deco在回答中所解释的):lanes不能处理用户数据。luasocket不提供任何其他访问套接字/套接字信息的方式

    我不想修补luasocket,因为我宁愿使用车道,我会继续坚持copas或Cous


    谢谢大家

    Lua车道为每个车道创建一个全新的(但最小的)Lua状态。 传递的任何upvalues或参数都是复制的,而不是引用的;这意味着正在复制AllClient表及其包含的套接字

    发生错误的原因是套接字是userdata,如果没有C模块的建议,Lua Lanes不知道如何复制这些数据。不幸的是,LuaSocket没有提供这样的建议。 (解决这个问题的方法有很多,但要小心:LuaSocket不是线程安全的,而且很难找到同步错误。)

    虽然它不能解决您的问题,但您应该注意,您需要在衍生车道中要求LuaSocket;默认情况下不会复制它

    解决! 这些都是从简单到困难的顺序(并且大部分是从我的另一个答案转录而来)

    单线程轮询 在LuaSocket中重复调用轮询函数:

    • 阻塞:调用
      socket。选择不带时间参数的
      ,等待socket可读
    • 非阻塞:调用
      socket。选择超时参数为
      0
      ,并在正在读取的套接字上使用
      sock:settimeout(0)
    只需反复调用这些。 我建议对非阻塞版本使用a,以允许程序的其他部分继续执行,而不会造成太多延迟

    (如果您选择此解决方案,我建议您进行复查。)

    双线程轮询 主线程根本不处理套接字。相反,它产生了另一个通道,它需要LuaSocket,处理所有客户机,并通过一个连接与主线程通信

    这可能是你最可行的选择

    多线程轮询 与上面相同,只是每个线程处理所有客户机的一个子集(1到1是可能的,但在大量客户机中会设置递减回报)

    我已经做了一个简单的例子。它依赖于LuaLanes 3.4.0()和修补的LuaSocket 2.0.2(,)

    结果是有希望的,尽管如果您从我的示例代码派生,您肯定应该重构它

    +内特
    这是一个很棒的图书馆。它提供了TCP和UDP之间的完美混合:需要时可靠,否则不可靠。它还抽象了操作系统特定的细节,就像LuaSocket一样。您可以使用luaapi绑定它,或者直接通过(推荐)访问它。

    编程Lua有一个例子(使用协同路由),您几乎可以直接使用它。在我看来,对于您的用例来说,协同程序将是一个更好的解决方案


    还有一种称自己为“基于可由TCP/IP服务器使用的协同路由的调度器”,但实际上您也可以使用它异步发送请求(使用
    addthread
    step
    调用的组合)。

    Deco:FYI,您在解决方案段落中的链接包含/编辑。感谢您提供的全面解决方案:)正如您所述,我正在尝试使用双线程或多线程轮询解决方案,但我仍然无法让lanes为我工作。(也感谢您指出我需要车道内的插座,我不知道)。我将编辑我的初始问题,发布一个我正在做的事情和失败的例子,如果你有时间看一看,也许我遗漏了什么?感谢链接,我想我最终可能会使用协同路由(并将从您的示例中学习dispatcher模型),但是如果我可以使用lanes,它似乎会更多。。优雅的“如果”是重要部分:P
    require ('socket')
    require ('lanes')
    local allClients = {}
    
    function theLane (id)
        print ('the id:', id) -- correctly prints out the id passed to the function
        local SOCKET = require ('socket')
        local client = allClients [id]
        print ('peer:', client:getpeername())
        client : close ()
    end
    
    local server = assert (SOCKET.bind ('*', 1234))
    local ip, port = server:getsockname ()
    local laneFunc = lanes.gen('', theLane)
    local client = server:accept ()
    allClients [1] = client
    local x = laneFunc (1)
    print (x[1])