我正在使用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。但是,#34;减轻网络负担&#34;解析器应该被停止(否则我们的Windows事件日志被Bonjour错误淹没:解析器&gt; 2分钟......)
因此,我看了一下苹果常见问题解答,因为我是一个持续的解决方案:
有一些罕见的应用程序需要保持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和地址记录查询的常规Resolve操作更有效。
好的,让我们测试一下Query函数:
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转换为vaild TXTRecord对象时触发?
答案 0 :(得分:0)
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
但是,我不喜欢提供信息,而是希望通过基于事件的监控来支持基于事件的解决方案。有什么想法吗?