创建一个被avahi广播的程序

6 投票
2 回答
4366 浏览
提问于 2025-04-15 14:54

我正在尝试写一个程序,目的是让数据可以通过网络进行传输,使用的是avahi这个工具。我查阅的文档上似乎说我需要先在dbus上注册这个服务,然后再把它连接到avahi上,但关于如何做到这一点的文档实在是太少了。有没有人知道哪里有好的文档可以参考?我正在查看以下这些:

python-dbus: http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html#exporting-objects

python-avahi: http://www.amk.ca/diary/2007/04/rough_notes_python_and_dbus.html

我对avahi的工作原理完全不熟悉,所以任何指点都将非常有帮助。

2 个回答

12

我知道这个回答来得有点晚,因为你的问题是在四年前问的。不过,这可能对其他人有帮助。

下面的内容是用 avahi/dbus 来发布一个服务:

import avahi
import dbus
from time import sleep


class ServiceAnnouncer:
    def __init__(self, name, service, port, txt):
        bus = dbus.SystemBus()
        server = dbus.Interface(bus.get_object(avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER)
        group = dbus.Interface(bus.get_object(avahi.DBUS_NAME, server.EntryGroupNew()),
                               avahi.DBUS_INTERFACE_ENTRY_GROUP)

        self._service_name = name
        index = 1
        while True:
            try:
                group.AddService(avahi.IF_UNSPEC, avahi.PROTO_INET, 0, self._service_name, service, '', '', port, avahi.string_array_to_txt_array(txt))
            except dbus.DBusException: # name collision -> rename
                index += 1
                self._service_name = '%s #%s' % (name, str(index))
            else:
                break

        group.Commit()

    def get_service_name(self):
        return self._service_name


if __name__ == '__main__':
    announcer = ServiceAnnouncer('Test Service', '_test._tcp', 12345, ['foo=bar', '42=true'])
    print announcer.get_service_name()

    sleep(42)

接下来用 avahi-browse 来确认这个服务确实已经发布:

micke@els-mifr-03:~$ avahi-browse -a -v -t -r 
Server version: avahi 0.6.30; Host name: els-mifr-03.local
E Ifce Prot Name                                          Type                 Domain
+   eth0 IPv4 Test Service                                  _test._tcp           local
=   eth0 IPv4 Test Service                                  _test._tcp           local
   hostname = [els-mifr-03.local]
   address = [10.9.0.153]
   port = [12345]
   txt = ["42=true" "foo=bar"]
1

Avahi其实就是一个客户端,它实现了一个叫做ZeroConfig的东西。简单来说,ZeroConfig是一种基于多播的DNS协议。你可以用Avahi来发布你“数据”的可用性,通过一些端点来实现。虽然实际的数据需要通过其他方式来获取,但通常你会注册一个端点,这样就可以通过你喜欢的方法来调用它。

撰写回答