2016-04-19 13 views
0

Ich benutze Apple Bonjour, um einige Client-Informationen auszusprechen.C# Apple Bonjour - wie zu überwachen Service-Datensätze in Windows

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; 
    } 
} 

Ich änderte den Quellcode, um Dinge einfach zu halten.

Ziel: bemerkt werden, sobald sich ein txtRecord eines Dienstes ändert.

Mein aktuelles Problem ist die (AAAA) Linie. Ohne den Resolver zu stoppen funktioniert alles wie gewünscht. Bei jeder TxtRecord-Änderung wird ServiceResolved aufgerufen. Um aber die Netzwerklast zu reduzieren, muss der Resolver gestoppt werden (andernfalls wird unser Windows-Ereignisprotokoll durch Bonjour-Fehler blockiert: Resolver> 2 min ...)

So habe ich mir Apples FAQ angesehen, weil ich eine kontinuierliche Lösung:

Es gibt einige seltene Anwendungen, die eine Resolve ausführen müssen, um TXT-Datensatzänderungen zu überwachen. Beispielsweise überwacht iChat kontinuierlich Änderungen an der Statusmeldung eines Buddys, die im Bonjour TXT-Datensatz gespeichert ist. Wenn Ihre Anwendung diese Art von Funktionalität erfordert, in Mac OS starten X 10.4 können Sie jetzt für TXT-Datensätze überwachen mit CFNetServiceMonitor und/oder [NSNetService startMonitoring] https://developer.apple.com/library/mac/qa/qa1297/_index.html

schlechte Sache, dass es keine Überwachung zu existieren scheint Schnittstelle beim C# Bonjour Wrapper.

Hinweis: Die Funktion DNSServiceQueryRecord können Sie Ihre Abfrage nur TXT-Datensätze beschränken, die effizienter ist als die reguläre Resolve Operationen verwendet, die eine Abfrage für SRV, TXT und Adresseinträge senden.

Okay, lassen Sie uns die Query-Funktion testen:

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 
    } 

Damm, um gute API-Beschreibung dessen, was ist die richtige DNSSDRRType, aber TXT scheint das richtige. Aber wie bekomme ich ein TXTRecord-Objekt daraus?

Gibt es einen besseren Anhaltspunkt, wie an einem Dienst TxtRecord Änderung ausgelöst oder zumindest, wie rdata in ein vaild TXTRecord Objekt konvertieren?

Antwort

0

Das TXTRecord Format in Technical Q&A QA1306 - Apple Developer Eigentlich gibt es erklärt zwei Formaten :-(In unserem Fall, dass ich dies für die Zeugung eines gültigen TXTRecord von rdata verwenden:

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 { 
     } 
    } 
} 

Leider ist die TXTRecord Klasse scheint buggy zu sein .

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

Aber statt die Informationen von pullung, ich möchte ein Ereignis-basierte Lösung mit einer ereignisbasierten Überwachung begünstigen. Jede Idee?