如何使用socket.select?

我需要一些帮助使用 socket "select" 函数。

我的服务器代码如下:

while true do
    for _,server in pairs(servers) do
        local client = server:accept()

        client:settimeout(5)

        local line, err = client:receive()
        if not err then
            client:send(line .. "_SERVER_SIDE\n")
        else
            client:Send("___ERRORPC"..err)
        end

        client:close()
    end
end

但现在我想使用 select 函数而不是像上述代码中的无限循环。

阅读此处:http://w3.impa.br/~diego/software/luasocket/socket.html

我知道我可以使用类似于以下内容的内容:

socket.select(servers, nil, 5)

但我不知道如何在上述代码中使用它。 有人能帮我吗?

我必须在 while true 语句内部使用它吗?

读取操作(第一个参数)意味着我只能执行 accept/receive] 吗?而第二个参数的意思是我只能执行 send?

点赞
用户90511
用户90511

根据文档,select 函数接收一个或两个套接字数组,返回一个可以安全地读取且不会阻塞的套接字数组、一个可以安全地写入且不会阻塞的套接字数组,以及一个可以安全地写入且不会阻塞的套接字数组。重要的一点是,第一个数组是既用于想要调用 accept 的服务器套接字,也用于想要调用 receive 的客户端套接字。

第二个参数仅是 select 的超时时间。它与您可以进行多少操作无关。

您需要更改代码的基本要素是,当接收调用因超时而失败时,您应将该套接字添加到传递给 select 的套接字数组中,而不是提供一个错误。这样,当该套接字再次活动时,select 可以告诉您。

2013-04-15 06:36:14
用户1442917
用户1442917

select 的文档中可以看到:"在调用 accept 之前在接收参数中使用服务器套接字来调用 select 并不保证 accept 会立即返回。使用 settimeout 方法,否则 accept 可能会永远阻塞。" 这意味着在调用 accept 之前需要使用 settimeout,但假设您有一个在 servers 表中可以使用的打开的连接列表,可以按照以下方式使用 select

local canread = socket.select(servers, nil, 1)
for _,client in ipairs(canread) do
  local line, err = client:receive()
  if not err then
      client:send(line .. "_SERVER_SIDE\n")
  else
      client:send("___ERRORPC"..err)
  end
end

socket.select 将阻塞最多 1 秒钟,但如果您提供的列表中有一个可读取的套接字,则会更快返回。如果使用 socket.select(servers, nil, 0),则可以无限期地阻塞;短时间地阻塞很有用,如果需要在等待输入时做一些其他工作。

更新为使用 ipairs 而不是 pairs,因为返回表既有数字键,也有套接字本身作为键,因此如果一个套接字可读,则返回的数组看起来像 {[1] = sock, [sock] = 1}

2013-04-15 19:13:25
用户8640577
用户8640577
local server = socket.bind("*",7777)
local client_tab = {}

while true do
    -- socket.select第一个参数是已连接套接字的表,
    -- 要获取已连接的套接字需要调用accept()方法
    -- 如果不想被阻塞,则需要调用settimeout(seconds)方法
    local recvt = socket.select(client_tab, nil, 1)
    server:settimeout(1)
    local client = server:accept()
    if client then
        client_tab[#client_tab+1] = client
    end
    if #recvt > 0 then
        -- 读取收到消息的客户端
    end
end
2019-07-17 04:25:41