如何通过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
相关产品推荐
相关产品推荐

