我正在使用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)线。在不停止解析器的情况下,一切都按需工作。每次Txt记录更改时,都会调用ServiceResolved。但是"为了减轻网络负担",解析器应该停止(否则,我们的windows事件日志会因Bonjour错误而被篡改:解析器>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#BonjourWrapper中似乎不存在监控接口。
注意:函数DNSServiceQueryRecord将允许您将查询限制为仅TXT记录,这比使用常规Resolve操作发送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
}
Damm,对什么是正确的DNSSRRT类型的API描述很好,但TXT似乎是正确的。但是如何从中获取TXTRecord对象?
有更好的线索吗,如何在服务TxtRecord更改时触发,或者至少如何将rdata转换为有效的TxtRecord对象?
TXTRecord格式在技术问答中有解释;一个QA1306-苹果开发者实际上有两种格式:-(在我们的情况下,我可以使用它从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
但是,我更喜欢基于事件的解决方案和基于事件的监控,而不是提取信息。知道吗?