tcl 中的服务发现
service discovery in tcl
我正在编写一个小 Tcl/Tk 脚本,它使用(自定义)网络应用程序(用 Python 编写)从一些中央存储中检索信息。
一切正常,但前提是事先知道网络服务器的地址。
所以我考虑添加某种服务发现,我的脚本会在本地网络上发现我的 Web 应用程序的所有 运行ning 实例,并自动使用它们。
我的第一个想法是使用 Zeroconf/Bonjour/Avahi,并让我的 Web 应用程序发布一个 _my-web-service._tcp
服务,其中包含实际的查询路径(tcl 客户端脚本应该用来访问数据)编码在 TXT
字段中:
avahi-publish-service MyService _my-web-service._tcp 8000 path=/data
不幸的是,我还没有找到 任何东西 将类似 zeroconf 的服务发现带入 Tcl 世界。
特别是,我正在查看 DNS entry on the Tcl Wiki,但这只会让我达到 mDNS
(我目前不知道如何从那里继续到 zeroconf 堆栈)。
我不是特别受 Zeroconf/Bonjour/Avahi 约束,但想 运行 我在 Linux/Windows/macOS、 和 上的脚本保留我的构建要求最低(也就是说:如果我不必编译自己的包装器代码来与每个平台的服务发现接口,我会更喜欢它)。告诉用户从 3rd 方来源安装 Bonjour 或诸如此类的东西是可以容忍的。
In particular, I was looking at the DNS entry on the Tcl Wiki but that
only gets me as far as mDNS (and i currently have no clue how to
proceed from there to zeroconf stack).
您查看的是右角,但 Tcl'ers Wiki 处的代码片段似乎已过时。我很好奇,给了它一些爱。
这是使用以下方法测试的:
% package req Tcl
8.6.12
% package req dns
1.4.1
% package req udp
1.0.11
...并通过以下方式在 macOS 上宣布一项示范性服务:
dns-sd -R "Index" _http._tcp . 80 path=/index22.html
我通过检索 DNS-SD (RFC 6763) 特定记录,主要是 SRV
记录中的目标和端口,设法使用修补后的 dns
包发现了上述服务(s),以及来自相应 TXT
记录的额外内容(例如路径):
set instanceName "Index._http._tcp.local"
set tok [::dns::resolve $instanceName -protocol mdns -type SRV]
if {[::dns::wait $tok] eq "ok"} {
set res [dict create {*}[lindex [::dns::result $tok] 0]]; # Pick first answer record, only!
array set SRV [dict get $res rdata]
::dns::cleanup $tok
set tok [::dns::resolve $instanceName -protocol mdns -type TXT]
if {[::dns::wait $tok] eq "ok"} {
array set TXT {}
foreach txt [::dns::result $tok] {
lassign [split [dict get $txt rdata] "="] k v
set TXT($k) $v
}
::dns::cleanup $tok
}
set tok [::dns::resolve $SRV(target) -protocol mdns -type A]
if {[::dns::wait $tok] eq "ok"} {
set res [dict create {*}[lindex [::dns::result $tok] 0]]; # Pick first answer record, only!
puts "Service IP: [dict get $res rdata]"
puts "Service port: $SRV(port)"
puts "Service options: [array get TXT]"
}
::dns::cleanup $tok
}
这将打印:
Service IP: 192.168.0.14
Service port: 80
Service options: path /index222.html
正在修补 tcllib 的 dns
来自 Tcl'ers Wiki 的片段需要修改,产生:
proc ::dns::UdpTransmit {token} {
# FRINK: nocheck
variable $token
upvar 0 $token state
# setup the timeout
if {$state(-timeout) > 0} {
set state(after) [after $state(-timeout) \
[list [namespace origin reset] \
$token timeout\
"operation timed out"]]
}
if {[llength [package provide ceptcl]] > 0} {
# using ceptcl
set state(sock) [cep -type datagram $state(-nameserver) $state(-port)]
chan configure $state(sock) -blocking 0
} else {
# using tcludp
set state(sock) [udp_open]
if { $state(-protocol) eq "mdns" } {
set state(-nameserver) "224.0.0.251"
set state(-port) 5353
chan configure $state(sock) -mcastadd $state(-nameserver);
}
}
chan configure $state(sock) -remote [list $state(-nameserver) $state(-port)] \
-translation binary \
-buffering none;
set state(status) connect
chan event $state(sock) readable [list [namespace current]::UdpEvent $token]
puts -nonewline $state(sock) $state(request)
return $token
}
背景:
- 这主要是为了反映
udp
API的变化(udp_conf
被chan configure /socket/ -remote
取代)
- ...而且:原始片段没有加入多播 IP 来侦听 mDNS 响应 (
-mcastadd
)。
- 除此之外,
dns
能够解码DNS资源记录(SRV,TXT)等。
(that is: i would prefer it, if i don't have to compile my own wrapper
code to interface with the service-discovery for each platform)
这样,您不必与任何 third-party 库或 exec
连接到某些可执行文件 (dns-sd
),但您必须将 Tcl/Tk 带有 platform-specific TclUDP 扩展名的脚本,作为 starpack 或 starkit,也许?
我正在编写一个小 Tcl/Tk 脚本,它使用(自定义)网络应用程序(用 Python 编写)从一些中央存储中检索信息。
一切正常,但前提是事先知道网络服务器的地址。
所以我考虑添加某种服务发现,我的脚本会在本地网络上发现我的 Web 应用程序的所有 运行ning 实例,并自动使用它们。
我的第一个想法是使用 Zeroconf/Bonjour/Avahi,并让我的 Web 应用程序发布一个 _my-web-service._tcp
服务,其中包含实际的查询路径(tcl 客户端脚本应该用来访问数据)编码在 TXT
字段中:
avahi-publish-service MyService _my-web-service._tcp 8000 path=/data
不幸的是,我还没有找到 任何东西 将类似 zeroconf 的服务发现带入 Tcl 世界。
特别是,我正在查看 DNS entry on the Tcl Wiki,但这只会让我达到 mDNS
(我目前不知道如何从那里继续到 zeroconf 堆栈)。
我不是特别受 Zeroconf/Bonjour/Avahi 约束,但想 运行 我在 Linux/Windows/macOS、 和 上的脚本保留我的构建要求最低(也就是说:如果我不必编译自己的包装器代码来与每个平台的服务发现接口,我会更喜欢它)。告诉用户从 3rd 方来源安装 Bonjour 或诸如此类的东西是可以容忍的。
In particular, I was looking at the DNS entry on the Tcl Wiki but that only gets me as far as mDNS (and i currently have no clue how to proceed from there to zeroconf stack).
您查看的是右角,但 Tcl'ers Wiki 处的代码片段似乎已过时。我很好奇,给了它一些爱。
这是使用以下方法测试的:
% package req Tcl
8.6.12
% package req dns
1.4.1
% package req udp
1.0.11
...并通过以下方式在 macOS 上宣布一项示范性服务:
dns-sd -R "Index" _http._tcp . 80 path=/index22.html
我通过检索 DNS-SD (RFC 6763) 特定记录,主要是 SRV
记录中的目标和端口,设法使用修补后的 dns
包发现了上述服务(s),以及来自相应 TXT
记录的额外内容(例如路径):
set instanceName "Index._http._tcp.local"
set tok [::dns::resolve $instanceName -protocol mdns -type SRV]
if {[::dns::wait $tok] eq "ok"} {
set res [dict create {*}[lindex [::dns::result $tok] 0]]; # Pick first answer record, only!
array set SRV [dict get $res rdata]
::dns::cleanup $tok
set tok [::dns::resolve $instanceName -protocol mdns -type TXT]
if {[::dns::wait $tok] eq "ok"} {
array set TXT {}
foreach txt [::dns::result $tok] {
lassign [split [dict get $txt rdata] "="] k v
set TXT($k) $v
}
::dns::cleanup $tok
}
set tok [::dns::resolve $SRV(target) -protocol mdns -type A]
if {[::dns::wait $tok] eq "ok"} {
set res [dict create {*}[lindex [::dns::result $tok] 0]]; # Pick first answer record, only!
puts "Service IP: [dict get $res rdata]"
puts "Service port: $SRV(port)"
puts "Service options: [array get TXT]"
}
::dns::cleanup $tok
}
这将打印:
Service IP: 192.168.0.14
Service port: 80
Service options: path /index222.html
正在修补 tcllib 的 dns
来自 Tcl'ers Wiki 的片段需要修改,产生:
proc ::dns::UdpTransmit {token} {
# FRINK: nocheck
variable $token
upvar 0 $token state
# setup the timeout
if {$state(-timeout) > 0} {
set state(after) [after $state(-timeout) \
[list [namespace origin reset] \
$token timeout\
"operation timed out"]]
}
if {[llength [package provide ceptcl]] > 0} {
# using ceptcl
set state(sock) [cep -type datagram $state(-nameserver) $state(-port)]
chan configure $state(sock) -blocking 0
} else {
# using tcludp
set state(sock) [udp_open]
if { $state(-protocol) eq "mdns" } {
set state(-nameserver) "224.0.0.251"
set state(-port) 5353
chan configure $state(sock) -mcastadd $state(-nameserver);
}
}
chan configure $state(sock) -remote [list $state(-nameserver) $state(-port)] \
-translation binary \
-buffering none;
set state(status) connect
chan event $state(sock) readable [list [namespace current]::UdpEvent $token]
puts -nonewline $state(sock) $state(request)
return $token
}
背景:
- 这主要是为了反映
udp
API的变化(udp_conf
被chan configure /socket/ -remote
取代) - ...而且:原始片段没有加入多播 IP 来侦听 mDNS 响应 (
-mcastadd
)。 - 除此之外,
dns
能够解码DNS资源记录(SRV,TXT)等。
(that is: i would prefer it, if i don't have to compile my own wrapper code to interface with the service-discovery for each platform)
这样,您不必与任何 third-party 库或 exec
连接到某些可执行文件 (dns-sd
),但您必须将 Tcl/Tk 带有 platform-specific TclUDP 扩展名的脚本,作为 starpack 或 starkit,也许?