我已经尝试这样做有一段时间了。我尝试遵循此http://lua.2524044.n2.nabble.com/UDP-Broadcast-td3995269.html,但无济于事。我已成功在客户端和服务器之间发送unicast消息。我已确认我的广播地址是正确的。我唯一能想到的另一件事就是嗅探我的接口以确保没有网络问题。我明天会处理这个问题,但想将其发布在这里,看看是否有人会注意到一个愚蠢的错误。
注意:我在同一台笔记本电脑上运行客户端和服务器。
客户
local socket = require("socket")
local s_address, s_port = "192.168.1.135", 33333
local d_address, d_port = "192.168.1.255", 22222
udp = socket.udp()
assert(udp)
assert(udp:settimeout(1))
assert(udp:setoption('broadcast', true))
assert(udp:setoption('dontroute',true))
assert(udp:setsockname(s_address, s_port))
while true do
tosend = string.format("client %s:%s", s_address, s_port)
print(string.format('sending to %s:%s...', d_address, d_port))
udp:sendto(tosend, d_address, d_port)
data, msg = udp:receive()
toprint = string.format("data = \"%s\"", data)
print(toprint)
socket.sleep(.5)
end
服务器
local socket = require("socket")
local s_address, s_port = "192.168.1.135", 11111
local p_address, p_port = "192.168.1.255", 22222
udp = socket.udp()
assert(udp)
assert(udp:setoption('broadcast', true))
assert(udp:setoption('dontroute',true))
assert(udp:settimeout(1))
assert(udp:setsockname(s_address, s_port))
assert(udp:setpeername(p_address, p_port))
while true do
data = udp:receive()
print(string.format('listening on %s:%s...', p_address, p_port))
toprint = string.format("data = \"%s\"", data)
print(toprint)
if data then
msg_back = "server received your message"
udp:send(msg_back)
end
socket.sleep(.5)
end
输出
两面不断打印
data = "nil"
。
我一直在寻求自己实现 luasocket 广播,这是互联网上为数不多的甚至提出该主题的页面之一。最后,在 luasocket API 和一些我能够适应的 python 代码之间,我找到了一个适合我的解决方案:
local socket = require 'socket'
local HOME_ADDR = '192.168.0.1'
local SUBNET_PATTERN = '%d+%.%d+%.%d+%.'
local function get_own_address()
local s = assert(socket.udp())
assert(s:setpeername(HOME_ADDR, 80))
local host = s:getsockname()
s:close()
return host
end
function broadcast(message, address, port)
local broadcaster = assert(socket:udp())
assert(broadcaster:setoption('broadcast', true))
assert(broadcaster:setoption('dontroute', true)) -- do we need this?
print(('Broadcasting %q to %s:%i'):format(message, address, port))
assert(broadcaster:sendto(message, address, port))
broadcaster:close()
end
function antiphony(message, timeout, call_port, response_port, response_mask)
local message, timeout, mask = tostring(message), tonumber(timeout) or 1.5, response_mask or '*a'
local send_port, recv_port = call_port or 10500, response_port or 10501
local broadcast_address = get_own_address():match(SUBNET_PATTERN) .. '255'
local listener = assert(socket.bind('*', recv_port, 64))
local clients, responses, starttime = {}, {}
listener:settimeout(0)
broadcast(message, broadcast_address, send_port)
starttime = socket.gettime()
repeat clients[listener:accept() or false] = true
until socket.gettime() - starttime > timeout
for client in pairs(clients) do
if client then
responses[client:getpeername()] = tostring(client:receive(mask))
client:close()
end
end
listener:close()
return responses
end
function listen(response_callback, timeout, listen_port, reply_port)
local recv_port, send_port = tonumber(listen_port) or 10500, tonumber(reply_port) or 10501
local callback = response_callback or function()end
local address = get_own_address():match(SUBNET_PATTERN) .. '255'
local sleeper = socket.udp()
sleeper:settimeout(timeout)
sleeper:setsockname(address, recv_port)
repeat
local data, ip, port = sleeper:receivefrom(1024)
if data then callback(ip, send_port, data) end
until not data
end
function respond(message, data_handler)
return function(ip_addr, port, data)
assert(ip_addr and port, ('Invalid address: %s:%s'):format(tostring(ip_addr), tostring(port)))
local msg = tostring(type(data_handler) == 'function' and (data_handler(data, message) or messsage) or message)
local sender = assert(socket.connect(ip_addr, port))
assert(sender:send(msg))
sender:close()
end
end
--[[
-- Listener / Responder:
listen(respond('polo', print), 600) -- 10 minute timeout
-- Broadcaster / Receiever:
for address, response in pairs(antiphony('marco')) do
print(address, response)
end
]]
我已经迟到了,但是对于有同样问题的人来说,你可以将所有客户端的IP和端口存储在一个表中,当你想广播一条消息时,你将循环遍历表中的所有客户端并向每个客户端发送一条消息其中。