Search code examples
lualuasocket

How do i use socket.select?


I need some help using socket "select" function.

My server code is like this:

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

But now i want to use the select function instead of make a forever loop like this.

Reading this: http://w3.impa.br/~diego/software/luasocket/socket.html

I know that i can use something simmilar than:

socket.select(servers, nil, 5)

But i don´t know how i can use this on the code above. Can anyone help me?

I will have to use this inside a while true statement?

The reading operation (first parameter) means that i can only make an accept/receive]? And the seconds parameter means that i can only make a send?


Solution

  • From the documentation for select: "calling select with a server socket in the receive parameter before a call to accept does not guarantee accept will return immediately. Use the settimeout method or accept might block forever." This means that you'd need to use settimeout before your accept call, but assuming you have a list of opened connections you can work with in servers table, you can use select in the following way:

    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 will block for up to 1 second, but will return sooner if there is a socket from the list you provided that can be read from. You can block indefinitely if you use socket.select(servers, nil, 0); blocking for some short time is useful if you need to do some other work while waiting for the input.

    Updated to use ipairs instead of pairs as the returns table is keyed both on numbers as well as on sockets themselves, so if one socket can be read from, the returned array looks like {[1] = sock, [sock] = 1}.