TCL中的服务发现

发布于 2025-02-01 02:25:01 字数 820 浏览 3 评论 0原文

我正在编写一些TCL/TK脚本,该脚本使用(自定义)Web应用程序(用Python编写)来从某些中央存储中检索信息。

一切都很好,但是只有事先已知Web服务器的地址。

因此,我考虑了添加某种服务发现,我的脚本将在本地网络上发现我的Web应用程序的所有运行实例,并自动使用它们。

我的第一个想法是使用zeroconf/bonjour/avahi,并让我的网络应用发布_my-web-service._tcp使用实际查询路径(TCL客户端脚本应访问该服务)数据)在txt字段中编码:

avahi-publish-service MyService _my-web-service._tcp 8000 path=/data

不幸的是,我还没有找到 将类似zeroconf的服务 - 发现带入tcl-world。

特别是,我正在看 dns tcl wiki ,但这只有得到我就mdns(我目前不知道如何从那里到达Zeroconf堆栈)。

我并不是特别绑定到zeroconf/bonjour/avahi,而是想在linux/windows/macos,上运行我的脚本我不必编译自己的包装代码即可与每个平台的服务划分进行交互)。不过,告诉用户安装Bonjour或第三方来源的Whatot将是可以忍受的。

I'm writing a little Tcl/Tk script, that uses a (custom) web-application (written in Python) to retrieve information from some central storage.

Everything works nicely, but only as long as the address of the webserver is known beforehand.

So I thought about adding some kind of service discovery, where my script would discover all running instances of my web-application on the local network, and automatically use them.

My first idea was to use Zeroconf/Bonjour/Avahi, and have my web-application publish a _my-web-service._tcp service with the actual query path (that the tcl client script should use to access the data) encoded in the TXT field:

avahi-publish-service MyService _my-web-service._tcp 8000 path=/data

Unfortunately, I haven't found anything that brings zeroconf-like service-discovery into the Tcl-world.

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).

I'm not especially bound to Zeroconf/Bonjour/Avahi, but would like to run my script on Linux/Windows/macOS, and keep my build requirements minimal (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). Telling the users to install Bonjour or whatnot from 3rd-party sources would be tolerable though.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

浅笑轻吟梦一曲 2025-02-08 02:25:01

特别是,我正在看TCL Wiki上的DNS条目
只能让我到MDNS(我目前不知道如何
从那里继续到Zeroconf堆栈)。

您正在查看右角,但是看起来已经过时了。我很好奇,给了一些爱。

使用以下方式对此进行了测试:

% 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软件包发现了上述服务,通过检索DNS-SD(RFC 6763)特定记录。 例如,路径)的目标和端口

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

,主要是srv 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_confchan configure/socket/socket/-rememote)代替
  • ...但也:原始摘要不会加入多播IP来聆听MDNS响应(-mcastadd)。
  • 除此之外,dns能够解码DNS资源记录(SRV,TXT)等。

(也就是说:如果我不必编译自己的包装器,我更喜欢它
代码以与每个平台的服务划分接口)

,您无需与任何第三方库或exec与某些可执行文件接口(dns-sd ),但是您将不得不将TCL/TK脚本与平台特定的TCLUDP扩展程序捆绑在一起,也许是Starpack或Starkit?

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).

You were looking at the right corner, but the code snippet at the Tcl'ers Wiki appears outdated. I was curious and gave it some love.

This was tested using:

% package req Tcl
8.6.12
% package req dns
1.4.1
% package req udp
1.0.11

... and by announcing an exemplary service on macOS via:

dns-sd -R "Index" _http._tcp . 80 path=/index22.html

I managed to discover the above service using the patched dns package, by retrieving the DNS-SD (RFC 6763) specific records, mainly the target and port from the SRV record(s), and extras (e.g., a path) from the corresponding TXT record(s):

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
}

This will print:

Service IP: 192.168.0.14
Service port: 80
Service options: path /index222.html

Patching tcllib's dns

The snippet from Tcl'ers Wiki needs to be modified, yielding:

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
}

Background:

  • This is mainly to reflect changes to udp API (udp_conf is replaced by chan configure /socket/ -remote)
  • ... but also: the original snippet does not join the multicast IP to listen for the mDNS responses (-mcastadd).
  • Other than that, dns is capable of decoding the DNS resource records (SRV, TXT) etc. just fine.

(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)

This way, you do not have to interface with any third-party library or exec to some executable (dns-sd), but you will have to bundle your Tcl/Tk script with the platform-specific TclUDP extension, as a starpack or starkit, maybe?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文