diff --git a/lualib/skynet/dns.lua b/lualib/skynet/dns.lua index 0b96f214..31c49eaa 100644 --- a/lualib/skynet/dns.lua +++ b/lualib/skynet/dns.lua @@ -219,7 +219,12 @@ local function unpack_rdata(qtype, chunk) end end -local dns_server +local dns_server = { + fd = nil, + address = nil, + port = nil, + retire = nil, +} local function resolve(content) if #content < DNS_HEADER_LEN then @@ -281,6 +286,33 @@ local function resolve(content) skynet.wakeup(resp.co) end +local DNS_SERVER_RETIRE = 60 * 100 +local function touch_server() + dns_server.retire = skynet.now() + if dns_server.fd then + return + end + dns_server.fd = socket.udp(function(str, from) + resolve(str) + end) + skynet.error(string.format("Udp server open %s:%s (%d)", dns_server.address, dns_server.port, dns_server.fd)) + socket.udp_connect(dns_server.fd, dns_server.address, dns_server.port) + local function check_alive() + if skynet.now() > dns_server.retire + DNS_SERVER_RETIRE then + local fd = dns_server.fd + if fd then + dns_server.fd = nil + socket.close(fd) + skynet.error(string.format("Udp server close %s:%s (%d)", dns_server.address, dns_server.port, fd)) + end + else + skynet.timeout( 2 * DNS_SERVER_RETIRE, check_alive) + end + end + + skynet.timeout( 2 * DNS_SERVER_RETIRE, check_alive) +end + function dns.server(server, port) if not server then local f = assert(io.open "/etc/resolv.conf") @@ -293,11 +325,11 @@ function dns.server(server, port) f:close() assert(server, "Can't get nameserver") end - dns_server = socket.udp(function(str, from) - resolve(str) - end) - socket.udp_connect(dns_server, server, port or 53) - return server + assert(dns_server.fd == nil) -- only set dns.server once + dns_server.address = server + dns_server.port = port or 53 + touch_server() + return dns_server.address end local function lookup_cache(name, qtype, ignorettl) @@ -354,8 +386,9 @@ function dns.resolve(name, ipv6) qdcount = 1, } local req = pack_header(question_header) .. pack_question(name, qtype, QCLASS.IN) - assert(dns_server, "Call dns.server first") - socket.write(dns_server, req) + assert(dns_server.address, "Call dns.server first") + touch_server() + socket.write(dns_server.fd, req) return suspend(question_header.tid, name, qtype) end diff --git a/test/testdns.lua b/test/testdns.lua index 01ac414a..0754f2ad 100644 --- a/test/testdns.lua +++ b/test/testdns.lua @@ -1,11 +1,20 @@ local skynet = require "skynet" local dns = require "skynet.dns" +local resolve_list = { + "github.com", + "stackoverflow.com", + "lua.com", +} + skynet.start(function() print("nameserver:", dns.server()) -- set nameserver -- you can specify the server like dns.server("8.8.4.4", 53) - local ip, ips = dns.resolve "github.com" - for k,v in ipairs(ips) do - print("github.com",v) + for _ , name in ipairs(resolve_list) do + local ip, ips = dns.resolve(name) + for k,v in ipairs(ips) do + print(name,v) + end + skynet.sleep(500) -- sleep 5 sec end end)