无线P2P服务发现的行为不符合预期.我看到间歇性的问题,DNSSD侦听器不会一直被调用,因此我不知道运行相同应用程序的附近设备.我使用以下两个API - 一个用于注册要由其他设备发现的服务,另一个用于发现在其他设备上运行的附近服务.任何想法,如果我在这里做错了或者是否有一些特定的其他Android API调用序列需要在我调用这些API之前进行,以确保在注册新服务时甚至是服务时始终调用侦听器在我们调用API以发现本地服务之前注册.
用于注册本地服务的API:
private void registerService() {
Map<String, String> values = new HashMap<String, String>();
values.put("name", "Steve");
values.put("port", "8080");
WifiP2pServiceInfo srvcInfo = WifiP2pDnsSdServiceInfo.newInstance(mMyDevice.deviceName, "_http._tcp", values);
manager.addLocalService(channel, srvcInfo, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
Toast.makeText(WiFiDirectActivity.this, "Local service added successfully",
Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(int reasonCode) {
Toast.makeText(WiFiDirectActivity.this, "Local service addition failed : " + reasonCode,
Toast.LENGTH_SHORT).show();
}
});
}
Run Code Online (Sandbox Code Playgroud)
用于发现本地服务的API:
public void discoverService() {
manager.clearServiceRequests(channel, null);
DnsSdTxtRecordListener txtListener = new DnsSdTxtRecordListener() {
@Override
/* Callback includes:
* …Run Code Online (Sandbox Code Playgroud) 我正在尝试在我公司的专有硬件设备上执行服务发现,该设备拥有自己的WiFi网络,并在该网络上宣传一项bonjour服务.当我连接到那个WiFi网络时,我正在使用NSD来发现该服务并解决它.
代码非常简单,通常效果很好而且很快.除了我有一个相当反复出现的问题(10次尝试中有5次)到目前为止本地化我的三星S8 +.到目前为止无法在S6或Pixel XL上重现.
问题是DiscoveryListener除了onDiscoveryStarted()之外从未做过任何事情,它只是永远运行.如果我杀了应用程序并重新开始,有时候它会继续挂起.
这就像有一个被阻塞的线程或东西,但是在日志中没有有用的信息(我能找到),而且我还没有发现任何东西可以锁定,因为我可以做些什么来从中恢复.
我添加了一个超时,它将在30秒后停止监听器,但通常在我重试之后它仍然无效.
服务发现过程包含在LiveData中,LiveData在活动时启动.
const val SERVICE_TYPE_FOO = "_foo._tcp."
private val serviceDiscoveryListener = ServiceDiscoveryListener()
override fun onActive() {
super.onActive()
stopRunnable = StopDiscoveryRunnable()
nsdManager.discoverServices(
SERVICE_TYPE_FOO,
NsdManager.PROTOCOL_DNS_SD,
serviceDiscoveryListener
)
handler.postDelayed(stopRunnable, SERVICE_DISCOVERY_TIMEOUT_MS)
}
private lateinit var stopRunnable: Runnable
private inner class StopDiscoveryRunnable : Runnable {
override fun run() {
try {
nsdManager.stopServiceDiscovery(serviceDiscoveryListener)
Timber.w("service discovery timed out")
postValue(ServiceDiscoveryState.Error)
} catch (e: Throwable) {
// no-op
}
}
}
Run Code Online (Sandbox Code Playgroud)
听众很简单......
private inner class ServiceDiscoveryListener : NsdManager.DiscoveryListener {
override fun onServiceFound(serviceInfo: NsdServiceInfo?) …Run Code Online (Sandbox Code Playgroud) 一旦通过DNS-SD发现服务,该主机的地址究竟如何得到解决,是否需要更多的时间/开销?
另外,如果我使用JmDNS或Bonjour有回调两个serviceFound和serviceResolved.如果我在设备发布某种服务的IP地址只是感兴趣,有没有获得比通过两个要去的地址更快/更有效的方式serviceFound和serviceResolved?
谢谢
我熟悉Bonjour在"本地"域名上的广告服务的用法.我已经完成了几个例子,我知道我使用的相应Cocoa类.
我很好奇我如何将一个简单的Bonjour服务宣传到不同的子网.具体来说,我正在尝试编写一个在我的桌面上运行的网络服务,该服务通过以太网连接.客户端在通过Wifi连接的移动设备(iPhone/iPad)上运行.在我的网络设置中,Wifi与以太网位于不同的子网上.但是,两者都落后于防火墙.我没有必要在防火墙外做广告,我只是希望wifi客户端能够看到以太网连接服务器所宣传的服务.
这可能吗?我知道Bonjour应该支持跨子网的通信,但是当我尝试阅读有关此功能的任何时候,它深入研究DNS记录和诸如此类的东西.我是一名应用程序开发人员...我不知道这些东西,我也不想让用户担心它.我错过了一些简单的事吗?
我正在构建一个使用Zeroconf的.net-microframework应用程序.现有的zeroconf解决方案似乎都依赖于dns-sd.dll或.netmf不支持的.net的其他一些互操作功能.
有没有你知道的纯粹的C#版zeroconf(或dns-sd)?
在Android上,我这样做是用一个简单的attacched地图作为信息来创建一个服务广播
HashMap<String, String> record = new HashMap<>();
record.put("info, "my android info");
WifiP2pDnsSdServiceInfo serviceInfo = WifiP2pDnsSdServiceInfo
.newInstance("_myservice", "_tcp", record);
WifiP2pManager manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
Channel channel = manager.initialize(this, this.getMainLooper(), null);
manager.addLocalService(channel, serviceInfo, null);
Run Code Online (Sandbox Code Playgroud)
检索另一个信号
manager.setDnsSdResponseListeners(channel, this, this);
@Override
public void onDnsSdTxtRecordAvailable(String fullDomainName, Map<String, String> txtRecordMap, WifiP2pDevice srcDevice)
Run Code Online (Sandbox Code Playgroud)
在iOS上,它是相同的服务名称和信息地图
MCPeerID* _myPeerId=[[MCPeerID alloc] initWithDisplayName:@"my ios peer"];
NSDictionary* _serviceInfo=@{@"info": @"my ios info"};
MCNearbyServiceAdvertiser* _serviceAdvertiser = [[MCNearbyServiceAdvertiser alloc]
initWithPeer:_myPeerId discoveryInfo:_serviceInfo serviceType:@"myservice"];
_serviceAdvertiser.delegate=advertiseDelegate;
MCNearbyServiceBrowser* _serviceBrowser=[[MCNearbyServiceBrowser alloc]
initWithPeer:_myPeerId serviceType:@"myservice"];
_serviceBrowser.delegate=browserDelegate;
[_serviceAdvertiser startAdvertisingPeer];
[_serviceBrowser startBrowsingForPeers];
Run Code Online (Sandbox Code Playgroud)
和代表们
-(void)browser:(MCNearbyServiceBrowser *)browser …Run Code Online (Sandbox Code Playgroud) 目前我正在使用NetServiceBrowser查找 Bonjour 服务并解析相应的地址和端口。
为了NWBrowser简化我的代码,我偶然发现它似乎提供了一个非常简单的界面来处理 Bonjour 发现。
但是,browseResultsChangedHandler返回包含 enum case 端点的结果和更改service。我试图从结果中获取地址和端口信息,但似乎NWEndpoint必须是枚举类型 .hostPort。
理想情况下,我会使用端点连接到服务器NWConnection,但是,我使用的是另一个不NWEndpoint直接处理 的库。
是否有(简单的)方法可以从NWEndpoint.service结果中获取地址和端口信息?
import Foundation
import Network
let browser = NWBrowser(for: .bonjour(type: "_http._tcp", domain: ""), using: NWParameters())
browser.browseResultsChangedHandler = { (results, changes) in
print("Results:")
for result in results
{
if case .service(let service) = result.endpoint
{
debugPrint(service)
}
else
{
assert(false, "This nevers gets executed")
}
}
print("Changes:")
for change in changes
{ …Run Code Online (Sandbox Code Playgroud) 我目前正在开发一个跨平台的应用程序(Win/OSX/iOS),它有一个C++(带有Boost)后端.在iOS和OSX上,我使用Cocoa Net服务浏览器委托功能通过mDNS发现嵌入式设备,然后将信息传递到后端以创建与之通信所需的对象.
我想对我的Windows MFC前端采取类似的方法,我发现这篇文章看起来完全符合我的要求.然而,似乎使用Bonjour SDK有一些非常讨厌的副作用 - 强迫你到MFC的静态链接,在我的情况下,我可以让它正确链接的唯一方法是根本不使用调试DLL,这是不理想的.
所以,Bonjour SDK对我来说并没有什么好处,因为它对我的项目施加了太多限制.使用Cocoa,我实际上只使用了很少的功能 - 实际上只有didFindService和netServiceDidResolveAddress.我想要做的就是找到给定类型的设备并获取其IP地址.
任何人都可以建议另一种解决方案,这将与Windows上的MFC前端一起使用吗?
我想使用iOS SDK解析DNS SRV记录.
我已经尝试过Apple提供的高级Bonjour API,但它们并不是我需要的.现在我正在使用DNS SD.
void *processQueryForSRVRecord(void *record) {
DNSServiceRef sdRef;
int context;
printf("Setting up query for record: %s\n", record);
DNSServiceQueryRecord(&sdRef, 0, 0, record, kDNSServiceType_SRV, kDNSServiceClass_IN, callback, &context);
printf("Processing query for record: %s\n", record);
DNSServiceProcessResult(sdRef);
printf("Deallocating query for record: %s\n", record);
DNSServiceRefDeallocate(sdRef);
return NULL;
}
Run Code Online (Sandbox Code Playgroud)
只要它只获得正确的SRV记录(例如:_xmpp-server._tcp.gmail.com),就可以正常工作,但是当记录键入错误时,DNSServiceProcessResult(sdRef)会进入无限循环.
有没有办法停止DNSServiceProcessResult或者我必须取消调用它的线程吗?
Heya 编码员/开发人员/网络人员/Devops/...
我在 WSL2(Windows 10 2004 版本)上下文中遇到mDNS/DNS-SD设置问题
我在家里有一个非常简单的设置,有一个主服务器和一个 Raspberry Pi,我想激活 DNS 服务发现,从而让我有一种简单的方法在我的 Raspberry PI 上自动发现我的服务器。
使用像dnssd这样的简单库,甚至自己广播正确的数据,我设法在不使用 WSL2 时使其轻松工作。但是我有一个要求让它在 WSL2 上工作,这就是事情变得复杂的地方。
由于 WSL2 在其自己的子网上运行,因此广播不再起作用。在子网上使用 mDNS 仅适用于该子网。然而,Windows 已经重新路由了主机和 WSL 之间的一些广播流量。
这很容易测试:Ping从我的服务器到依赖 mDNS 的 Pi 的 Avahi 地址做一个简单的工作。
在屏幕左侧,您可以看到 Wireshark 在主机网络接口上捕获的流量,在右侧,您可以看到 Wireshark 在 WSL 网络接口上捕获的流量。前3行是一个简单的ping:它是在WSL的上下文中执行的,但是这里出现的IP地址172.28.192.1——不是WSL客户端的IP地址,而是WSL内部DNS服务器的IP地址。正如您在右侧看到的那样,它在主机上完美地重新路由,带有 Windows 主机的 IP 地址:192.168.0.39
但是,由脚本执行的第二个查询具有 WSL 源 IP ( 172.28.204.42),并且该查询不会在主机上重新路由。
我的网络知识非常有限,我不明白这是如何工作的,以及如何让 WSL 在主机上路由我自己的 mDNS 查询。一个疯狂的猜测是它与 iptables 有关,但就我而言。
如果有人知道为什么它适用于 DNS 服务器源地址而不是当我自己执行它时,这将对我有很大帮助!