如何用Boost Asio(C++)区分USB端口被占用或不存在?
如何通过Boost Asio区分USB端口不存在与被占用状态
你的核心问题在于原代码用catch (...)吞掉了所有异常,导致无法区分"端口不存在"和"端口被占用"这两种不同的错误场景。Boost Asio在操作失败时会抛出boost::system::system_error异常,其中携带了具体的错误码,我们可以通过这些错误码精准区分两种状态。
关键思路
- 捕获具体异常:替换
catch (...)为捕获boost::system::system_error,获取其中的error_code对象。 - 根据平台判断错误码:
- Windows平台:
- 端口不存在:错误码对应
ERROR_FILE_NOT_FOUND(数值2) - 端口被占用:错误码对应
ERROR_ACCESS_DENIED(数值5)
- 端口不存在:错误码对应
- Linux平台:
- 端口不存在:错误码对应
ENOENT(数值2) - 端口被占用:错误码对应
EBUSY(数值16)或EACCES(数值13)
- 端口不存在:错误码对应
- Windows平台:
- 简化端口检测逻辑:原代码中的
CDCDeviceExist和预存设备列表逻辑可以简化,直接通过尝试打开端口的结果来判断状态。
修改后的代码示例
#include <boost/asio.hpp> #include <boost/system/system_error.hpp> // 定义端口状态枚举,方便区分不同场景 enum class PortStatus { AVAILABLE, OCCUPIED, NOT_EXIST }; PortStatus checkPortStatus(const std::string& deviceName) { boost::asio::io_context io; boost::asio::serial_port device(io); boost::system::error_code ec; device.open(deviceName, ec); if (!ec) { device.close(); return PortStatus::AVAILABLE; } // 根据平台匹配错误码 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) if (ec.value() == 2) { // 端口不存在 return PortStatus::NOT_EXIST; } else if (ec.value() == 5) { // 端口被占用 return PortStatus::OCCUPIED; } #else if (ec.value() == 2) { // 端口不存在 return PortStatus::NOT_EXIST; } else if (ec.value() == 16 || ec.value() == 13) { // 端口被占用 return PortStatus::OCCUPIED; } #endif // 未知错误默认按不存在处理 return PortStatus::NOT_EXIST; } std::vector<std::string> Tools_Hardware_USB_Protocols_CDC_getDeviceNames() { std::vector<std::string> deviceNames; char deviceName[20]; for (int i = 0; i < 127; i++) { #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) sprintf_s(deviceName, "COM%i", i); if (checkPortStatus(deviceName) == PortStatus::AVAILABLE) { deviceNames.push_back(deviceName); } #else // 修正原代码笔误:ttyAMC -> ttyACM sprintf_s(deviceName, "/dev/ttyACM%i", i); if (checkPortStatus(deviceName) == PortStatus::AVAILABLE) { deviceNames.push_back(deviceName); } sprintf_s(deviceName, "/dev/ttyUSB%i", i); if (checkPortStatus(deviceName) == PortStatus::AVAILABLE) { deviceNames.push_back(deviceName); } #endif } return deviceNames; }
代码说明
- 新增
PortStatus枚举明确端口状态,方便后续扩展处理被占用端口的统计逻辑。 checkPortStatus函数通过open操作的错误码直接判断状态,避免了原代码中预检测逻辑的不可靠性。- 移除了吞掉所有异常的
catch (...),改用error_code处理错误(也可以选择捕获system_error异常来获取错误码)。 - 修正了Linux平台下的设备名称笔误:原代码的
ttyAMC应为ttyACM。
额外提示
如果需要分别收集"被占用"或"不存在"的端口列表,只需在遍历过程中对不同PortStatus值做对应的收集逻辑即可。
内容的提问来源于stack exchange,提问作者euraad
相关产品推荐
相关产品推荐

