2

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

4

2 回答 2

4

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

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

于 2013-03-04T10:38:42.407 回答
0

您需要在 accept() 之前设置超时以允许非阻塞套接字。根据 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
于 2018-11-09T01:39:58.580 回答