我需要一些使用套接字“选择”功能的帮助。
我的服务器代码是这样的:
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
但现在我想使用select函数而不是像这样永久循环。
阅读本文:http://w3.impa.br/~diego/software/luasocket/socket.html
我知道我可以使用类似于:
的东西socket.select(servers, nil, 5)
但我不知道如何在上面的代码中使用它。任何人都可以帮助我吗?
我将不得不在一段时间内使用这个真实的陈述?
读取操作(第一个参数)意味着我只能进行接受/接收]?而seconds参数意味着我只能进行发送?
答案 0 :(得分:3)
根据文档,select选择接收一个或两个套接字数组并返回一个可以安全地无阻塞地读取的套接字数组和一个可以安全地写入但没有阻塞的套接字数组和一个可以插入的套接字数组安全地写,没有阻止。重要的一点是,第一个阵列适用于您希望调用接受的服务器套接字以及要呼叫接收的客户端套接字。
seconds参数只是select的超时。这与你可以进行多少操作无关。
您必须在代码中更改的基本事项是,当接收调用因超时而失败,或者发出错误时,您应该将该套接字添加到您传递给选择的套接字数组中。通过这种方式,您可以选择告诉您该套接字何时再次激活。
答案 1 :(得分:2)
从select
的文档中:“在调用accept之前调用receive参数中的服务器套接字并不保证接受将立即返回。使用settimeout方法或者接受可能会永久阻止。”这意味着您需要在settimeout
调用之前使用accept
,但假设您有一个可以在servers
表中使用的已打开连接的列表,则可以使用{{1以下列方式:
select
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
将阻止最多1秒钟,但如果您提供的可从中读取的套接字中有套接字,则会立即返回。如果您使用socket.select
,则可以无限期阻止;如果你在等待输入时需要做一些其他的工作,那么在短时间内阻塞是很有用的。
更新为使用socket.select(servers, nil, 0)
而不是ipairs
,因为返回表在数字和套接字本身都是键控的,所以如果可以读取一个套接字,则返回的数组看起来像{{ 1}}。
答案 2 :(得分:0)
单个演示
local server = socket.bind("*",7777)
local client_tab = {}
while true do
-- socket.select first param is a table of connected socket,
-- you want a connected socket,you need to call accept()
-- if you do not want to block,you should call settimeout(seconds)
local recvt = socket.select(client_tab, nil, 1)
server:settimeout(1)
local client = server:accept()
if client then
client_tab[#client_tab+1] = client
end
if #recvt > 0 then
-- read clients in recvt
end
end