Lua中推送数据到websocket浏览器客户端

我想使用一个NodeMCU设备(基于Lua)作为websocket服务器,连接到一个或多个浏览器客户端。

幸运的是,这里有相应的代码: NodeMCU Websocket Server (感谢@creationix和/或@moononournation)

它的功能如描述的那样,我能够从客户端向NodeMCU服务器发送消息,服务器基于接收到的消息做出响应。很棒。

我的问题是:

  1. 如何在不必以响应客户端请求的形式(独立发送数据)下向客户端发送消息? 当我尝试调用socket.send()时,会提示socket未找到,我理解,但无法解决它!:(
  2. 为什么 decode() 函数输出 extra 变量? 这个用来干什么的?我猜它是为了解决数据包溢出的问题,但我似乎无法使它返回任何内容,无论我的消息长度如何。
  3. 在listen方法中,为什么作者添加了队列系统? 这是必要的还是为了处理可能同时接收到多个消息的应用程序?理想情况下,我想去掉它。

我将代码简化如下:

(不包括decode()encode()函数-请参见上面的完整脚本)

net.createServer(net.TCP):listen(80, function(conn)

  local buffer = false
  local socket = {}
  local queue = {}
  local waiting = false

  local function onSend()
    if queue[1] then
      local data = table.remove(queue, 1)
      return conn:send(data, onSend)
    end
    waiting = false
  end

  function socket.send(...)
    local data = encode(...)
    if not waiting then
      waiting = true
      conn:send(data, onSend)
    else
      queue[#queue + 1] = data
    end
  end

  conn:on("receive", function(_, chunk)

    if buffer then
      buffer = buffer .. chunk
      while true do
        local extra, payload, opcode = decode(buffer)

        if opcode==8 then
          print("Websocket client disconnected")
        end

        --print(type(extra), payload, opcode)
        if not extra then return end
        buffer = extra
        socket.onmessage(payload, opcode)
      end
    end

    local _, e, method = string.find(chunk, "([A-Z]+) /[^\r]* HTTP/%d%.%d\r\n")
    local key, name, value

    for name, value in string.gmatch(chunk, "([^ ]+): *([^\r]+)\r\n") do
      if string.lower(name) == "sec-websocket-key" then
        key = value
        break
      end
    end

    if method == "GET" and key then

      acceptkey=crypto.toBase64(crypto.hash("sha1", key.."258EAFA5-E914-47DA-95CA-C5AB0DC85B11"))

      conn:send(
        "HTTP/1.1 101 Switching Protocols\r\n"..
        "Upgrade: websocket\r\nConnection: Upgrade\r\n"..
        "Sec-WebSocket-Accept: "..acceptkey.."\r\n\r\n",
        function ()

          print("新的websocket客户端连接成功")

          function socket.onmessage(payload,opcode)
            socket.send("收到你的数据", 1)
            print("PAYLOAD = "..payload)
            --print("OPCODE = "..opcode)
          end

        end)
      buffer = ""
    else
      conn:send(
        "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 12\r\n\r\nHello World!",
        conn.close)
    end

  end)
end)
点赞
用户131929
用户131929

我只能回答一个问题,其余的可能更适合向图书馆的作者咨询。此外,SO是一个你通常只问一个问题的格式。

如何向客户端发送信息,而不必将其作为响应客户端请求而发送(独立发送数据)?

您无法这样做。如果客户端不首先联系服务器并建立套接字连接,服务器将不知道将消息发送到何处。即使使用SSE(服务器推送事件),也是客户端首先建立到服务器的连接。

2019-09-13 17:21:09