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

如何用Boost Asio(C++)区分USB端口被占用或不存在?

如何通过Boost Asio区分USB端口不存在与被占用状态

你的核心问题在于原代码用catch (...)吞掉了所有异常,导致无法区分"端口不存在"和"端口被占用"这两种不同的错误场景。Boost Asio在操作失败时会抛出boost::system::system_error异常,其中携带了具体的错误码,我们可以通过这些错误码精准区分两种状态。

关键思路

  1. 捕获具体异常:替换catch (...)为捕获boost::system::system_error,获取其中的error_code对象。
  2. 根据平台判断错误码:
    • Windows平台:
      • 端口不存在:错误码对应ERROR_FILE_NOT_FOUND(数值2)
      • 端口被占用:错误码对应ERROR_ACCESS_DENIED(数值5)
    • Linux平台:
      • 端口不存在:错误码对应ENOENT(数值2)
      • 端口被占用:错误码对应EBUSY(数值16)或EACCES(数值13)
  3. 简化端口检测逻辑:原代码中的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 00:05:37