HarmonyOS 鸿蒙Next中MDNS搜索不到服务
HarmonyOS 鸿蒙Next中MDNS搜索不到服务
各位大佬们为什么我写的这个mdns搜索不到任何服务:
下面是ArkTS写的mdns搜索服务:
// 开始服务发现
public async startDiscovery(
context: common.Context, // 使用正确的 common.Context 类型
serviceType: string = "_http._tcp.",
domain: string = "local."): Promise<mdns.LocalServiceInfo> {
// 检查是否已经在搜索
if (this.isSearching) {
LogE(TAG, "🔗尝试开始新的服务发现,但是已经有一个正在进行");
throw new Error("Discovery already in progress");
}
// 取消之前的搜索
await this.destroy();
// 创建并启动新的搜索任务
this.isSearching = true;
LogI(TAG, `🔗开始搜索服务: ${serviceType}`);
return new Promise<mdns.LocalServiceInfo>((resolve, reject) => {
// 保存 resolve/reject 引用
this.resolvePromise = resolve;
this.rejectPromise = reject;
// 设置超时自动终止
// const timeoutId = setTimeout(() => {
// LogE(TAG, `服务发现超时 (${this.timeoutMs}ms)`);
// this.cleanup();
// reject(new Error("Discovery timeout"));
// }, this.timeoutMs);
try {
// 创建 mdns 实例
this.discovery = mdns.createDiscoveryService(context, serviceType);
// 开始搜索
this.discovery.startSearchingMDNS();
// 事件监听
this.discovery.on("discoveryStart", (info: mdns.DiscoveryEventInfo) => {
LogI(TAG, `🔗发现开始: ${info.serviceInfo.serviceType}`);
});
this.discovery.on("discoveryStop", () => {
LogI(TAG, `🔗发现停止`);
});
this.discovery.on("serviceFound", async (info: mdns.LocalServiceInfo) => {
LogI(TAG, `🔗发现服务: ${info.serviceName}`);
try {
// 解析服务详情
const resolvedInfo = await this.resolveService(context, info);
LogI(TAG, `🔗解析成功: ${resolvedInfo.serviceName} IP: ${resolvedInfo.host?.address}`);
// 成功返回结果
this.resolvePromise?.(resolvedInfo);
this.cleanup();
// clearTimeout(timeoutId);
} catch (resolveErr) {
LogE(TAG, `🔗解析失败: ${resolveErr.message}`);
// 继续等待其他服务
}
});
this.discovery.on("serviceLost", (info: mdns.LocalServiceInfo) => {
LogW(TAG, `🔗服务丢失: ${info.serviceName}`);
});
} catch (e) {
LogE(TAG, `🔗启动发现失败: ${e.message}`);
this.rejectPromise?.(e);
this.cleanup();
// clearTimeout(timeoutId);
}
});
}
为了测试如上代码,我写了一个这个mdns服务去广播:
const os = require('os');
const http = require('http'); // ✅ 补全点 1: 引入http模块
const mdns = require('multicast-dns')();
/**
* 获取本机的局域网IPv4地址
* @returns {string} 本机IP地址,如果找不到则返回 '0.0.0.0'
*/
function getLocalIpAddress() {
const interfaces = os.networkInterfaces();
for (const name of Object.keys(interfaces)) {
for (const iface of interfaces[name]) {
// 跳过非IPv4地址和内部地址(如 127.0.0.1)
if (iface.family !== 'IPv4' || iface.internal !== false) {
continue;
}
return iface.address;
}
}
return '0.0.0.0'; // 作为回退
}
// --- 1. 获取主机和服务的动态信息 ---
const HOST_IP = getLocalIpAddress();
const HOST_NAME = os.hostname().replace(/\.local$/, ''); // 获取主机名并移除可能存在的.local后缀
// 检查是否成功获取IP
if (HOST_IP === '0.0.0.0') {
console.error('错误:无法找到有效的本地局域网IP地址。请检查您的网络连接。');
process.exit(1);
}
const SERVICE = {
name: 'drec-simulator-service', // 服务的实例名
type: '_http._tcp', // 服务的类型
port: 8489,
txt: { webdav_port: '49151' } // 附加的TXT信息
};
// --- 2. 构造符合规范的mDNS记录 ---
// 构造 TXT 记录的 Buffer
const txtData = Object.entries(SERVICE.txt).map(([k, v]) => `${k}=${v}`);
const records = [
// 记录 A: 广播服务类型
{
name: '_services._dns-sd._udp.local',
type: 'PTR',
ttl: 28800,
data: `${SERVICE.type}.local`
},
// 记录 B: 广播服务实例
{
name: `${SERVICE.type}.local`,
type: 'PTR',
ttl: 28800,
data: `${SERVICE.name}.${SERVICE.type}.local`
},
// 记录 C: 定义服务的位置 (SRV)
{
name: `${SERVICE.name}.${SERVICE.type}.local`,
type: 'SRV',
ttl: 120,
data: {
port: SERVICE.port,
target: `${HOST_NAME}.local`
}
},
// 记录 D: 定义附加文本信息 (TXT)
{
name: `${SERVICE.name}.${SERVICE.type}.local`,
type: 'TXT',
ttl: 4500,
data: txtData
},
// 记录 E: 定义主机名的IP地址 (A)
{
name: `${HOST_NAME}.local`,
type: 'A',
ttl: 120,
data: HOST_IP
}
];
// --- 3. 启动一个真正的HTTP服务器来响应连接 --- ✅ 补全点 2: 整个HTTP服务器逻辑
const httpServer = http.createServer((req, res) => {
// 当从客户端(如HarmonyOS应用)收到一个HTTP请求时,此函数将被执行
const clientInfo = `${req.socket.remoteAddress}:${req.socket.remotePort}`;
console.log(`\n[HTTP Server] 收到来自客户端 ${clientInfo} 的请求!`);
console.log(` > 请求路径: ${req.url}`);
// 准备要发送回客户端的消息
const responseMessage = `你好,来自 ${clientInfo} 的客户端!你的请求我已收到。`;
// 设置响应头,指定内容为UTF-8编码的纯文本
res.writeHead(200, {
'Content-Type': 'text/plain; charset=utf-8'
});
// 将消息作为响应发送回客户端
res.end(responseMessage);
});
// 让HTTP服务器在mDNS服务指定的端口上开始监听
httpServer.listen(SERVICE.port, HOST_IP, () => {
console.log(`\n[HTTP Server] 服务端已在 http://${HOST_IP}:${SERVICE.port}/ 上成功启动并监听连接。`);
});
// --- 4. 发布mDNS服务并处理进程 ---
// 打印mDNS服务信息以供调试
console.log('\n准备发布 mDNS 服务:');
console.log(` - 服务实例名: ${SERVICE.name}`);
console.log(` - 服务类型: ${SERVICE.type}.local`);
console.log(` - 主机名: ${HOST_NAME}.local`);
console.log(` - IP 地址: ${HOST_IP}`);
console.log(` - 端口: ${SERVICE.port}`);
console.log(` - TXT 记录:`, SERVICE.txt);
// 响应 mDNS 查询
mdns.on('query', (query) => {
// 可以选择性地在这里打印查询日志,用于调试
console.log('收到查询:', query.questions.map(q => q.name));
mdns.respond(records);
});
console.log(`\n[mDNS Server] 服务已发布。其他设备现在应该可以发现 '${SERVICE.name}'。`);
console.log('按 Ctrl+C 停止服务。');
// 优雅地停止服务
process.on('SIGINT', () => {
console.log('\n收到 Ctrl+C,正在关闭服务...');
// ✅ 补全点 3: 确保HTTP服务器也被关闭
httpServer.close(() => {
console.log('[HTTP Server] HTTP服务器已关闭。');
// 在HTTP服务器关闭后,再关闭mDNS服务
mdns.destroy(() => {
console.log('[mDNS Server] mDNS服务已取消发布。');
process.exit();
});
});
});
更多关于HarmonyOS 鸿蒙Next中MDNS搜索不到服务的实战教程也可以访问 https://www.itying.com/category-93-b0.html
好长的代码。看了下你的代码中serviceType参数传递的"_http._tcp.“多了一个点号,改为”_http._tcp"。服务端代码的_services._dns-sd._udp.local记录类型应为PTR,但数据字段应指向服务实例名称。
{
name: '_services._dns-sd._udp.local',
type: 'PTR',
data: `${SERVICE.type}.local`
}
SRV记录的target字段应包含完整主机名:
{
name: `${SERVICE.name}.${SERVICE.type}.local`,
type: 'SRV',
data: {
port: SERVICE.port,
target: `${HOST_NAME}.local` // 必须带.local后缀
}
}
更多关于HarmonyOS 鸿蒙Next中MDNS搜索不到服务的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
无人帮忙吗,泪目了,我这mdns按照官方写的为什么搜索不到服务呢?
在HarmonyOS鸿蒙Next中MDNS搜索不到服务可能原因如下:
- 网络配置问题:确保设备在同一局域网且未启用AP隔离
- 防火墙限制:检查网络防火墙是否阻止了5353/UDP端口通信
- 服务注册失败:目标服务可能未正确注册mDNS服务
- 协议实现差异:鸿蒙Next使用Hichain可能与其他系统mDNS实现存在兼容性问题
- 权限问题:应用需申请ohos.permission.INTERNET权限
调试建议:
- 使用同一网络下的其他设备验证mDNS服务是否正常广播
- 通过抓包工具检查mDNS组播报文是否正常收发
从代码来看,你的mDNS服务发现逻辑基本正确,但有几个关键点需要检查:
-
确保设备在同一局域网内,并且防火墙没有阻止mDNS流量(UDP端口5353)
-
检查服务类型格式是否正确,在HarmonyOS中应该使用"_http._tcp"格式,不要加".local"后缀
-
确认你的测试设备是否支持mDNS协议,可以尝试使用其他工具(如dns-sd或avahi-browse)验证服务是否正常广播
-
在HarmonyOS端,确保已添加必要的权限:
"reqPermissions": [
{
"name": "ohos.permission.INTERNET"
}
]
- 调试建议:
- 检查discoveryStart事件是否触发
- 尝试缩短TTL时间(如120秒)
- 确认context参数正确传递
- 检查日志中是否有错误输出
如果问题仍然存在,可以尝试简化代码,先只实现最基本的服务发现功能,再逐步添加其他逻辑。