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

C语言Socket传输bitmap到服务器仅显灰度 收发字节数一致如何解决

问题根因分析及修复方案

核心问题1:TCP流接收未做完整性校验

你虽然统计了总收发字节数一致,但分两次调用recv的逻辑存在缺陷:第一次接收sizeof(BITMAPINFOHEADER)(40字节)时,TCP是流协议,单次recv返回值可能小于请求长度,比如第一次只收到了部分头信息,就会导致bi结构体的biBitCount、biSizeImage等核心字段错误。如果biBitCount被错误解析为8位,就会直接出现灰度显示的问题。

核心问题2:服务端位图创建逻辑位深不匹配

你用CreateCompatibleBitmap创建的位图位深和当前窗口DC的位深绑定,如果服务端系统显示位深和客户端设定的32位不匹配,SetDIBits做颜色空间转换时就会出现显示异常。


修复代码

1. 服务端FD_READ分支修改

case FD_READ:
    hdcWindow = GetDC(hwnd);
    hdcbuffer = CreateCompatibleDC(hdcWindow);
    int recv_len = 0, ret = 0;

    // 循环接收完整的BITMAPINFOHEADER,避免头信息不完整
    while(recv_len < sizeof(bi)) {
        ret = recv(cs, (char*)&bi + recv_len, sizeof(bi) - recv_len, 0);
        if(ret <= 0) goto read_cleanup; // 连接异常直接退出
        recv_len += ret;
    }

    buffer = (char*)malloc(bi.biSizeImage);
    recv_len = 0;
    // 循环接收完整的图像数据
    while(recv_len < bi.biSizeImage) {
        ret = recv(cs, buffer + recv_len, bi.biSizeImage - recv_len, 0);
        if(ret <= 0) {
            free(buffer);
            goto read_cleanup;
        }
        recv_len += ret;
    }

    // 直接创建和客户端位深匹配的DIB Section,避免颜色转换异常
    BITMAPINFO bmi = {0};
    memcpy(&bmi.bmiHeader, &bi, sizeof(BITMAPINFOHEADER));
    void* pBits = NULL;
    hbm = CreateDIBSection(hdcWindow, &bmi, DIB_RGB_COLORS, &pBits, NULL, 0);
    memcpy(pBits, buffer, bi.biSizeImage);

    SelectObject(hdcbuffer, hbm);
    BitBlt(hdcWindow,
        0, 0,
        bi.biWidth, bi.biHeight,
        hdcbuffer,
        0, 0,
        SRCCOPY);

    free(buffer);
read_cleanup:
    DeleteObject(hbm);
    ReleaseDC(hwnd, hdcWindow);
    DeleteDC(hdcbuffer);
    break;

2. 客户端可选优化

建议客户端发送前也校验send的返回值,循环发送完整数据,避免单次send未发全导致的后续异常。


内容的提问来源于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 22:36:03