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

C++蓝牙Socket调用recv()接收数据末尾出现垃圾字符问题排查

乱码原因分析
  • 核心原因:字符输出无结束符
    你定义的接收缓冲区char charOut[outLen]长度仅为1,recv()成功读取1字节的字符5后,缓冲区没有剩余空间存储C风格字符串必需的\0结束标记。cout输出char*类型时会默认从起始地址一直读内存,直到碰到\0才停止,因此会输出缓冲区后方栈空间的未初始化垃圾值,你看到的╠就是Windows调试模式下栈未初始化区域的默认填充值0xCC。
  • 额外输出了错误码
    接收逻辑末尾你直接执行了cout << WSAGetLastError();,接收正常时该函数返回值为0,这个0直接被输出到了乱码的末尾,就是你看到的乱码最后的0。
其他潜在问题
  • 未判断recv()的返回值:如果接收失败、连接断开,recv()会返回SOCKET_ERROR,此时直接输出缓冲区内容会导致不可预期的结果。
  • 资源使用不规范:每次收发都重复执行WSAStartup()、创建 socket、连接蓝牙设备,结束后没有调用WSACleanup()释放Winsock资源,存在资源泄漏风险,且连接频繁断开重连也容易导致数据丢失。
修复示例(仅修改recv2函数逻辑)
void recv2() {
    WSADATA wsa;
    memset(&wsa, 0, sizeof(wsa));
    int error = WSAStartup(MAKEWORD(2, 2), &wsa);
    SOCKET btSocket = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
    SOCKADDR_BTH sockAddr;
    memset(&sockAddr, 0, sizeof(sockAddr));
    sockAddr.addressFamily = AF_BTH;
    sockAddr.serviceClassId = RFCOMM_PROTOCOL_UUID;
    sockAddr.port = BT_PORT_ANY;
    BTH_ADDR tmpaddr = 0;
    sscanf_s("7C:9E:BD:4C:BF:B2", "%02x:%02x:%02x:%02x:%02x:%02x", &aaddr[0], &aaddr[1], &aaddr[2], &aaddr[3], &aaddr[4], &aaddr[5]);
    sockAddr.btAddr = 0;
    for (i = 0; i < 6; i++) {
        tmpaddr = (BTH_ADDR)(aaddr[i] & 0xff);
        sockAddr.btAddr = (sockAddr.btAddr << 8) + tmpaddr;
    }
    connect(btSocket, (SOCKADDR*)&sockAddr, sizeof(sockAddr));
    // 缓冲区长度+1预留结束符位置
    const int outLen = 1;
    char charOut[outLen + 1];
    int ret = recv(btSocket, charOut, outLen, 0);
    if (ret > 0) {
        // 手动添加字符串结束符
        charOut[ret] = '\0';
        cout << charOut;
    } else {
        // 仅出错时打印错误码
        cout << "接收失败,错误码:" << WSAGetLastError();
    }
    closesocket(btSocket);
    WSACleanup();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 14:09:00