2016-04-19 15 views
0

AppleのBonjourを使用してクライアント情報を発音しています。C#Apple Bonjour - 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; 
    } 
} 

私は物事を単純にするためにソースコードを変更しました。

目的:サービスのtxtRecordが変更されるとすぐに通知されます。

実際の問題は(AAAA)行です。リゾルバを止めることなく、すべてが必要なものとして機能します。 TxtRecordの変更ごとに、ServiceResolvedが呼び出されます。しかし、 "ネットワークの負担を軽減する"ためにはリゾルバを停止する必要があります(そうでなければ、WindowsのイベントログはBonjourのエラーによって解決されます:resolver> 2 min ...)

こうしてAppleのFAQを見ました。継続的な解決策:

TXTレコードの変更を監視するためにResolveを実行し続ける必要がある、まれなアプリケーションがあります。たとえば、iChatは、Bonjour TXTレコードに保存されているバディのステータスメッセージの変更を継続的に監視します。アプリケーションがこの種の機能を必要とする場合、あなたは今CFNetServiceMonitorを使用してTXTレコードを監視できるのMac OS X 10.4以降で、および/または[NSNetService startMonitoring] https://developer.apple.com/library/mac/qa/qa1297/_index.html

監視を存在していないようですということは悪いことC#Bonjour Wrapperのインターフェイス。

注:機能DNSServiceQueryRecordはSRV、TXTおよびアドレスレコードのクエリを送信する通常の解決操作を使用するよりも効率的である、あなただけの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だが、TXTは、正しいものを思われるものの良いAPI-説明します。しかし、どのようにしてTXTRecordオブジェクトを取得するのですか?

サービスのTxtRecordの変更でトリガする方法、または少なくともrdataをvaildのTXTRecordオブジェクトに変換する方法がわかりますか?

答えて

0

TXTRecord形式は、当社の場合、私はRDATAから有効なTXTRecordを取得するためにこれを使用することができます:-(実際には二つの形式がありますTechnical Q&A QA1306 - Apple Developer で説明されています。

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 

しかし、その代わりに情報をpullungの、私は、イベントベースのモニタリングとイベントベースのソリューションを好むしたいと思います。任意のアイデア?

関連する問題