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