【问题标题】:C# Apple Bonjour - how to monitor service records within WindowsC# Apple Bonjour - 如何在 Windows 中监控服务记录
【发布时间】:2016-04-19 05:02:18
【问题描述】:

我正在使用 Apples Bonjour 来发音一些客户信息。

class BonjourExample 
{
   private Bonjour.DNSSDEventManager m_eventManager;;
   private Bonjour.DNSSDService      m_service;
   private Bonjour.DNSSDService      m_browser;
   private Bonjour.DNSSDService      m_resolver;

   private Init() 
   {
      m_service      = new DNSSDService();
      m_eventManager = new DNSSDEventManager();
      m_eventManager.ServiceFound        += new _IDNSSDEvents_ServiceFoundEventHandler(this.ServiceFound);
      m_eventManager.ServiceLost         += new _IDNSSDEvents_ServiceLostEventHandler(this.ServiceLost);
      m_eventManager.ServiceResolved     += new _IDNSSDEvents_ServiceResolvedEventHandler(this.ServiceResolved);
      m_eventManager.QueryRecordAnswered += new _IDNSSDEvents_QueryRecordAnsweredEventHandler(this.QueryAnswered);
      m_eventManager.OperationFailed     += new _IDNSSDEvents_OperationFailedEventHandler(this.OperationFailed);

     m_bonjourBrowser = m_bonjourService.Browse( 0, 0, "_xyz._tcp", null, m_eventManager );
   }

   private void ServiceFound(DNSSDService sref, DNSSDFlags flags, uint ifIndex, String serviceName, String regType, String domain )
   {
      m_resolver = m_service.Resolve( 0, ifIndex, serviceName, regType, domain, m_eventManager ) );
   }

   public void ServiceLost( DNSSDService sref, DNSSDFlags flags, uint ifIndex, String serviceName, String regType, String domain ) 
   {
   }

   public void ServiceResolved( DNSSDService sref, DNSSDFlags flags, uint ifIndex, String serviceName, String hostName, ushort port, TXTRecord txtRecord ) 
   {
       //... get the information ...

       //
       // Stop the resolve to reduce the burden on the network // <- copied from Apples examples
       //
       m_resolver.Stop(); // (AAAA) <- just a merker ;-)
       m_resolver = null;
   }
}

我修改了源代码以保持简单。

目标:一旦服务的 txtRecord 发生变化,就会引起注意。

我的实际问题是 (AAAA) 行。在不停止解析器的情况下,一切都按需要进行。每次 TxtRecord 更改时都会调用 ServiceResolved。但是“为了减轻网络负担”,解析器应该被停止(否则我们的 Windows 事件日志被 Bonjour 错误淹没:解析器 > 2 分钟...)

因此我查看了 Apples 常见问题解答,因为我是一个持续的解决方案:

有一些罕见的应用程序需要保持 Resolve 运行以监控 TXT 记录更改。例如,iChat 会持续监控存储在 Bonjour TXT 记录中的好友状态消息的变化。如果您的应用程序需要这种类型的功能,从 Mac OS X 10.4 开始,您现在可以使用 CFNetServiceMonitor 和/或 [NSNetService startMonitoring] 监控 TXT 记录 https://developer.apple.com/library/mac/qa/qa1297/_index.html

C# Bonjour Wrapper 似乎没有监控接口。

注意:函数 DNSServiceQueryRecord 将允许您将查询限制为仅 TXT 记录,这比使用发送 SRV、TXT 和地址记录查询的常规解析操作更有效。

好,我们来测试一下查询功能:

   public void ServiceResolved( DNSSDService sref, DNSSDFlags flags, uint ifIndex, String serviceName, String hostName, ushort port, TXTRecord txtRecord ) 
   {
       m_resolver.Stop(); 
       m_resolver = null;

       // just to test the query interface:
       m_service.QueryRecord( 0, 0, serviceName, DNSSDRRType.kDNSSDType_TXT, DNSSDRRClass.kDNSSDClass_IN, m_bonjourEventManager ) );
   }

   public void QueryRecordAnswered( DNSSDService service, DNSSDFlags flags, uint ifIndex, string fullname, DNSSDRRType rrtype, DNSSDRRClass rrclass, object rdata, uint ttl )
   {
      // DAMM, how to get a TXTRecord-objet of rdata? Using binaryFormatter serializiation fails

      var arrBytes = (Byte[])rdata;
      var txt = System.Text.Encoding.ASCII.GetString( bytes); /es, its the record
   }

该死,对于正确的 DNSSDRRType 的良好 API 描述,但 TXT 似乎是正确的。但是如何从中获取 TXTRecord 对象呢?

任何更好的线索,如何在服务 TxtRecord 更改时触发,或者至少如何将 rdata 转换为有效的 TxtRecord 对象?

【问题讨论】:

    标签: c# windows bonjour


    【解决方案1】:

    TXTRecord 格式在Technical Q&A QA1306 - Apple Developer 中有解释 实际上有两种格式 :-( 在我们的例子中,我可以使用它从 rdata 获取有效的 TXTRecord:

    public void QueryRecordAnswered( DNSSDService service, DNSSDFlags flags, uint ifIndex, string fullname, DNSSDRRType rrtype, DNSSDRRClass rrclass, object rdata, uint ttl )
    {   
        if( rdata != null ) {
            try {
                var bytes = (Byte[])rdata;
                TXTRecord txtRecord = new TXTRecord();
                for( int index = 0; index < bytes.Length; ) {
                    Int32 length = bytes[index];
                    String text = System.Text.Encoding.ASCII.GetString( bytes, index+1, length );
                    String[]  keyValue = text.Split( new char[] { '=' }, 2 );
                    if( keyValue.Length == 2 ) {
                        txtRecord.SetValue( keyValue[0], keyValue[1] );
                    }
    
                    index += 1 + length;
                }
            }
            catch {
            }
        }
    }
    

    不幸的是,TXTRecord 类似乎有问题。

    txtRecord.SetValue( "KEY", "VALUE" );
    bool b = txtRecord.ContainsKey( "KEY" ); -> returns false
    

    但是,我不喜欢提取信息,而是支持基于事件的解决方案和基于事件的监控。有什么想法吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-04
      • 1970-01-01
      相关资源
      最近更新 更多