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

C语言Socket传输位图收发字节数一致但服务端无法显示位图问题

问题根因分析

核心问题集中在变量生命周期、事件处理逻辑、GDI资源管理三类,以下是具体错误点:

  • 静态变量未重置:服务端的count、客户端的count/length都用了static修饰,单次收发完成后变量值不会复位,第二次及之后调用收发逻辑时会直接跳过循环,使用未初始化或无效的内存数据。就算是首次运行,若FD_READ被多次触发,也会因为count初始值不对导致接收逻辑异常。
  • 元数据接收无校验:服务端在FD_ACCEPT事件中直接调用一次recv读取BITMAPINFOHEADER,没有校验是否收满sizeof(BITMAPINFOHEADER)字节,一旦接收不完整,后续使用的bi.biSizeImage、bi.biWidth等核心参数全是错误值,哪怕后续图像数据接收字节数匹配也无法正常解码。
  • GDI资源生命周期错误:服务端的hdcWindow、hdcbuffer是静态变量,却在FD_READ处理完后直接释放,后续再次触发收发/绘制逻辑时,使用的是已经无效的DC句柄,CreateCompatibleBitmap、SetDIBits等GDI接口会直接调用失败。
  • 绘制逻辑位置错误:直接在FD_READ中调用BitBlt绘制到窗口DC,只要窗口触发重绘(比如拖动、缩放、被其他窗口遮挡),绘制内容就会被系统擦除,看起来就像没有显示成功。
  • 无错误校验逻辑:所有Socket、GDI接口的返回值都没有做校验,无法定位是接收环节、解码环节还是绘制环节出的问题。
修复方案

按照优先级依次修改以下内容即可解决问题:

  1. 移除收发逻辑中临时变量的static修饰,或者每次进入收发流程时手动复位变量:
    服务端进入FD_READ时首先将count = 0;客户端进入CaptureAnImage时将count、length复位为0。
  2. 补充元数据接收校验,确保收满sizeof(BITMAPINFOHEADER)字节后再使用bi的字段:
    int recv_len = 0;
    while(recv_len < sizeof(bi)) {
        int n = recv(cs, (char*)&bi + recv_len, sizeof(bi) - recv_len, 0);
        if(n <= 0) break;
        recv_len += n;
    }
    
  3. 调整GDI资源生命周期:
    • 要么将hdcWindow、hdcbuffer的释放逻辑移到WM_DESTROY中,不要在FD_READ里提前释放
    • 要么每次绘制时临时创建DC、使用完立即释放,不要用静态变量存储DC句柄
  4. 把绘制逻辑迁移到WM_PAINT事件中:
    FD_READ收到完整位图数据后,保存好解码后的HBITMAP,调用InvalidateRect触发窗口重绘,在WM_PAINT中通过BeginPaint获取DC完成绘制,避免窗口重绘时内容丢失。
  5. 补充所有关键接口的返回值校验:
    对recv、send、CreateCompatibleBitmap、SetDIBits的返回值做判断,失败时调用WSAGetLastError()、GetLastError()打印错误码,快速定位问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 23:06:03