You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Electron局域网消息应用服务发现功能实现问题求助

局域网Electron应用设备发现解决方案(基于Bonjour)

常见问题排查与修复步骤

  • 权限缺失:Electron应用需要局域网通信权限,macOS需在打包时添加com.apple.security.network.server和com.apple.security.network.client权限;Windows需确保防火墙允许应用通过私有网络。
  • 服务类型不规范:Bonjour服务类型必须遵循_服务名._协议格式,避免和通用HTTP服务冲突,比如用_rifflo._tcp替代单纯的http。
  • 子进程环境异常:Electron主进程的__dirname可能和子进程不一致,需显式指定Node执行路径和环境变量。
  • 网卡绑定错误:默认情况下Bonjour可能绑定到localhost或IPv6地址,需手动指定本地IPv4地址。
  • 退出清理不彻底:原代码仅监听exit事件,无法捕获Electron的关闭信号,需补充SIGINT/SIGTERM监听。

修正后的代码实现

main.js 调整(完善子进程管理)

const { app, BrowserWindow, ipcMain } = require('electron');
const childProcess = require('child_process');
let serverProcess = null;

function createWindow() {
    const win = new BrowserWindow({
        fullscreen: true,
        minWidth: 1024,
        minHeight: 720,
        frame: false,
        webPreferences: {
            contextIsolation: true,
            preload: preloadPath, // 确保preloadPath已正确定义
        },
    });

    win.loadURL('http://localhost:3000');

    // 用Electron自带的Node执行子进程,避免环境不一致
    serverProcess = childProcess.spawn(process.execPath, ['server.js'], {
        cwd: __dirname,
        env: { ...process.env, NODE_ENV: process.env.NODE_ENV || 'development' }
    });

    serverProcess.stdout.on('data', (data) => {
        console.log(`Server output: ${data.toString().trim()}`);
    });

    serverProcess.stderr.on('data', (data) => {
        console.error(`Server error: ${data.toString().trim()}`);
    });

    serverProcess.on('exit', (code) => {
        console.log(`Server process exited with code ${code}`);
    });
}

app.whenReady().then(createWindow);

// 应用关闭前终止子进程,确保服务正确停止
app.on('before-quit', () => {
    if (serverProcess) {
        serverProcess.kill('SIGINT');
    }
});

app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') {
        app.quit();
    }
});

app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
        createWindow();
    }
});

server.js 修正(规范服务发现逻辑)

const bonjour = require('bonjour')();
const os = require('os');

// 获取本地可用IPv4地址,避免绑定到localhost
function getLocalIP() {
    const interfaces = os.networkInterfaces();
    for (const iface of Object.values(interfaces)) {
        for (const alias of iface) {
            if (alias.family === 'IPv4' && !alias.internal) {
                return alias.address;
            }
        }
    }
    return '127.0.0.1';
}

const localIP = getLocalIP();
const servicePort = 3000;

// 发布自定义Bonjour服务,避免和其他服务冲突
const service = bonjour.publish({
    name: `RiFFlo-${localIP}`, // 用IP区分同一局域网的多个实例
    type: '_rifflo._tcp',
    port: servicePort,
    host: localIP,
    txt: { version: '1.0', role: 'peer' } // 附加元数据,用于后续信令服务器选举
});

console.log(`Service advertised at ${localIP}:${servicePort}`);

// 发现同类型的局域网服务
const browser = bonjour.find({
    type: '_rifflo._tcp',
    protocol: 'tcp'
});

browser.on('up', (remoteService) => {
    // 过滤掉自己的服务实例
    if (remoteService.host !== localIP) {
        console.log('Found peer service:', {
            name: remoteService.name,
            ip: remoteService.host,
            port: remoteService.port,
            metadata: remoteService.txt
        });
        // 这里可添加信令服务器选举逻辑,比如选IP最小的实例作为服务器
    }
});

browser.on('down', (remoteService) => {
    console.log('Peer service offline:', remoteService.name);
});

browser.start();

// 完善退出清理逻辑,确保服务停止
function cleanup() {
    service.stop(() => {
        browser.stop();
        bonjour.destroy();
        console.log('Service cleaned up, exiting.');
        process.exit(0);
    });
}

process.on('SIGINT', cleanup);
process.on('SIGTERM', cleanup);
process.on('exit', cleanup);

额外优化建议

  • 信令服务器选举:在发现的服务中,可通过IP排序、元数据标记等方式自动选出一个实例作为信令服务器,其他实例主动连接该服务器建立P2P通道。
  • UDP广播备用方案:如果Bonjour仍存在兼容性问题,可以改用UDP广播实现设备发现——每隔1秒向局域网广播地址(如192.168.1.255)发送标识包,其他实例监听对应端口并回复自身信息。
  • 打包配置:使用Electron Builder打包时,需确保bonjour依赖被正确打包;macOS需在entitlements.plist中添加网络权限配置。

内容的提问来源于stack exchange,提问作者D V

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 02:20:36