多个连接Lua插座

Multiple connections Lua Sockets

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


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

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


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

By default, all I/O operations are blocking. That is, any call to the methods send, receive, and accept will block indefinitely, until the operation completes. The settimeout method defines a limit on the amount of time the I/O methods can block

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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.."\
\
"
)
            end
          end--for
          logdbmessage(clientnames[i], clientmessage)
        end--if


      end--if

    end--if
  end--for

end--while