多个连接Lua套接字

时间:2013-03-03 21:28:44

标签: sockets lua

我正在使用Lua套接字和TCP创建一个类似聊天客户端和服务器的IRC。我想弄清楚的主要问题是如何使客户端和服务器监听消息并同时发送它们。因为在服务器上执行socket:accept()时它会停止程序直到创建连接。有没有办法接受多个连接并将它们存储到表中?

2 个答案:

答案 0 :(得分:4)

这看起来与像Copas这样的调度员解决的问题完全一样。您应该阅读:http://keplerproject.github.com/copas/manual.html#why - 即使您不想使用Copas,它也会帮助您弄清楚如何解决该问题。

基本上,您需要在select()之前使用accept()。请注意,即使您这样做,实际上也不能保证accept()会立即返回,因此您也应该使用settimeout()(请参阅http://w3.impa.br/~diego/software/luasocket/socket.html#select

答案 1 :(得分:0)

您需要在accept()之前设置settimeout,以允许非阻塞套接字。根据Lua套接字的文档,accept()方法将阻止下一个连接。

  

默认情况下,所有I / O操作均处于阻塞状态。也就是说,对方法send,receive和accept的任何调用都将无限期地阻塞,直到操作完成。 settimeout方法定义了I / O方法可以阻止的时间量限制

以下是聊天服务器的工作演示。您可以使用telnet进行连接。

socket = require("socket") -- import lib

-- define host and port
host = "*"
port = 8080

-- create socket and bind to an available port
server = assert(socket.bind(host, port))

-- get local port number and IP
ip, port = server:getsockname()

totalclient = 0 -- store the total connections
clients = {} -- e.g. clients[1] = 0xSocketAddress
clientnames = {} -- e.g. clientnames[1] = "john"

-- start the loop to listening connection
while true do

  -- new client connected, settimeout to not block connetcion
  server:settimeout(0.01)
  local client, err = server:accept();

  -- print the info of new client and add new client to the table
  if (not err) then
    clientname = client:receive()
    totalclient = totalclient + 1
    clients[totalclient] = client
    clientnames[totalclient] = clientname
    print(">> "..clientname.." connected from " .. tostring(client:getsockname()) .." at " ..os.date("%m/%d/%Y %H:%M:%S"))
  end

  -- loop through the client table
  for i = 1, totalclient do
    -- if there is client, listen to that client
    if (clients[i] ~= nil) then
      clients[totalclient]:settimeout(0.01) -- prevent blocking
      clientmessage, err = clients[i]:receive() -- accept data from client

      -- check if there is something sent to server, and no error occured
      if (err == nil and clientmessage ~= nil) then

        -- loop through the list of client to send broadcast message
        else
          for j = 1, totalclient do
            -- check not to send broadcast to the speaker
            if clients[i] ~= clients[j] then
              clients[j]:send(tostring("["..clientnames[i]).."]: " ..clientmessage.."\r\n")
            end
          end--for
          logdbmessage(clientnames[i], clientmessage)
        end--if


      end--if

    end--if
  end--for

end--while