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

如何通过C++ DBus调用Connman连接WPA2 WiFi网络?

使用C++ DBus连接受保护WiFi(基于Connman)

核心逻辑

Connman通过系统DBus提供WiFi管理接口,实现连接需完成三个关键步骤:扫描并定位目标WiFi服务、配置加密参数、激活连接。

依赖准备

  • 确保系统预装connman及开发包(如Debian/Ubuntu系的libconnman-dev)
  • 安装C++ DBus开发库:libdbus-1-dev

代码示例

以下是基于原生DBus库的实现,支持连接PSK加密的WiFi:

#include <dbus/dbus.h>
#include <iostream>
#include <string>
#include <cstring>

// 简易错误处理函数
void check_dbus_error(DBusError* error, const char* err_msg) {
    if (dbus_error_is_set(error)) {
        std::cerr << err_msg << ": " << error->message << std::endl;
        dbus_error_free(error);
        exit(EXIT_FAILURE);
    }
}

int main(int argc, char** argv) {
    if (argc != 3) {
        std::cerr << "用法: " << argv[0] << " <WiFi名称> <PSK密码>" << std::endl;
        return EXIT_FAILURE;
    }
    const char* target_ssid = argv[1];
    const char* psk_pass = argv[2];

    DBusError error;
    dbus_error_init(&error);

    // 连接系统DBus总线
    DBusConnection* bus_conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
    check_dbus_error(&error, "连接系统DBus失败");

    // 1. 获取所有WiFi服务,定位目标SSID的服务路径
    DBusMessage* get_svc_msg = dbus_message_new_method_call(
        "net.connman",
        "/",
        "net.connman.Manager",
        "GetServices"
    );
    if (!get_svc_msg) {
        std::cerr << "创建GetServices请求失败" << std::endl;
        return EXIT_FAILURE;
    }

    DBusMessage* svc_reply = dbus_connection_send_with_reply_and_block(bus_conn, get_svc_msg, -1, &error);
    check_dbus_error(&error, "调用GetServices失败");
    dbus_message_unref(get_svc_msg);

    std::string target_svc_path;
    DBusMessageIter reply_iter, array_iter, dict_entry_iter;
    dbus_message_iter_init(svc_reply, &reply_iter);
    if (dbus_message_iter_get_arg_type(&reply_iter) == DBUS_TYPE_ARRAY) {
        dbus_message_iter_recurse(&reply_iter, &array_iter);
        while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_DICT_ENTRY) {
            dbus_message_iter_recurse(&array_iter, &dict_entry_iter);

            // 提取服务路径
            char* svc_path;
            dbus_message_iter_get_basic(&dict_entry_iter, &svc_path);
            dbus_message_iter_next(&dict_entry_iter);

            // 遍历服务属性,匹配SSID
            DBusMessageIter props_iter;
            dbus_message_iter_recurse(&dict_entry_iter, &props_iter);
            bool ssid_found = false;
            while (dbus_message_iter_get_arg_type(&props_iter) == DBUS_TYPE_DICT_ENTRY) {
                DBusMessageIter prop_entry_iter;
                dbus_message_iter_recurse(&props_iter, &prop_entry_iter);

                char* prop_key;
                dbus_message_iter_get_basic(&prop_entry_iter, &prop_key);
                dbus_message_iter_next(&prop_entry_iter);

                if (strcmp(prop_key, "Name") == 0) {
                    char* svc_name;
                    dbus_message_iter_get_basic(&prop_entry_iter, &svc_name);
                    if (strcmp(svc_name, target_ssid) == 0) {
                        target_svc_path = svc_path;
                        ssid_found = true;
                        break;
                    }
                }
                dbus_message_iter_next(&props_iter);
            }
            if (ssid_found) break;
            dbus_message_iter_next(&array_iter);
        }
    }
    dbus_message_unref(svc_reply);

    if (target_svc_path.empty()) {
        std::cerr << "未找到WiFi: " << target_ssid << std::endl;
        return EXIT_FAILURE;
    }

    // 2. 配置PSK加密参数
    DBusMessage* set_prop_msg = dbus_message_new_method_call(
        "net.connman",
        target_svc_path.c_str(),
        "net.connman.Service",
        "SetProperty"
    );
    if (!set_prop_msg) {
        std::cerr << "创建SetProperty请求失败" << std::endl;
        return EXIT_FAILURE;
    }

    DBusMessageIter args_iter;
    dbus_message_iter_init_append(set_prop_msg, &args_iter);
    const char* sec_prop_key = "Security";
    dbus_message_iter_append_basic(&args_iter, DBUS_TYPE_STRING, &sec_prop_key);

    // 构建Security属性字典
    DBusMessageIter sec_dict_iter, entry_iter;
    dbus_message_iter_open_container(&args_iter, DBUS_TYPE_ARRAY, "{sv}", &sec_dict_iter);

    // 添加加密类型为PSK
    dbus_message_iter_open_container(&sec_dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &entry_iter);
    const char* type_key = "Type";
    const char* type_val = "psk";
    dbus_message_iter_append_basic(&entry_iter, DBUS_TYPE_STRING, &type_key);
    dbus_message_iter_append_basic(&entry_iter, DBUS_TYPE_STRING, &type_val);
    dbus_message_iter_close_container(&sec_dict_iter, &entry_iter);

    // 添加PSK密码
    dbus_message_iter_open_container(&sec_dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &entry_iter);
    const char* pass_key = "Passphrase";
    dbus_message_iter_append_basic(&entry_iter, DBUS_TYPE_STRING, &pass_key);
    dbus_message_iter_append_basic(&entry_iter, DBUS_TYPE_STRING, &psk_pass);
    dbus_message_iter_close_container(&sec_dict_iter, &entry_iter);

    dbus_message_iter_close_container(&args_iter, &sec_dict_iter);

    DBusMessage* prop_reply = dbus_connection_send_with_reply_and_block(bus_conn, set_prop_msg, -1, &error);
    check_dbus_error(&error, "设置加密参数失败");
    dbus_message_unref(set_prop_msg);
    dbus_message_unref(prop_reply);

    // 3. 激活WiFi连接
    DBusMessage* connect_msg = dbus_message_new_method_call(
        "net.connman",
        target_svc_path.c_str(),
        "net.connman.Service",
        "Connect"
    );
    if (!connect_msg) {
        std::cerr << "创建Connect请求失败" << std::endl;
        return EXIT_FAILURE;
    }

    DBusMessage* connect_reply = dbus_connection_send_with_reply_and_block(bus_conn, connect_msg, -1, &error);
    check_dbus_error(&error, "连接WiFi失败");
    std::cout << "成功连接到WiFi: " << target_ssid << std::endl;

    // 清理资源
    dbus_message_unref(connect_msg);
    dbus_message_unref(connect_reply);
    dbus_connection_unref(bus_conn);

    return EXIT_SUCCESS;
}

编译命令

g++ -o connman_wifi connman_wifi.cpp `pkg-config --cflags --libs dbus-1`

注意事项

  • 必须以root权限运行,Connman的DBus接口需要管理员权限
  • 若未找到目标SSID,可先调用net.connman.Manager.Scan方法触发WiFi扫描
  • 代码仅支持PSK加密,如需其他加密方式(如WPA2-EAP),需修改Security属性的配置内容

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 22:48:53