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
相关产品推荐
相关产品推荐

