0

我想通过winsock 发送桌面截图。

因此,有四个任务:

Save bitmap to buffer
Write data across wire using a socket
Read data from wire using a socket
Load a bitmap from a buffer

我已使用 GetDIBits 将位图保存到 char 数组中。将数据写入服务器,我已经完成了,但我有问题。为了将数据从服务器写入客户端,我是否只需要使用 1 个 recv() 调用(我正在使用 TCP),还是需要将其拆分为多个部分?我读过 TCP 是流概念,我不必担心数据包,因为这对我来说是抽象的?

我将如何将 GetDIBits 中的信息加载到位图中并将其显示在主窗口上?

我猜我必须使用 SetDIBits,但我在哪些设备上下文中使用?

服务器截图捕获器在这里:

 HDC handle_ScreenDC = GetDC(NULL);
HDC handle_MemoryDC = CreateCompatibleDC(handle_ScreenDC);
BITMAP bitmap;


int x = GetDeviceCaps(handle_ScreenDC, HORZRES);
int y = GetDeviceCaps(handle_ScreenDC, VERTRES);

HBITMAP handle_Bitmap = CreateCompatibleBitmap(handle_ScreenDC, x, y);
SelectObject(handle_MemoryDC, handle_Bitmap);

BitBlt(handle_MemoryDC, 0, 0, x, y, handle_ScreenDC, 0, 0, SRCCOPY);

GetObject(handle_Bitmap, sizeof(BITMAP), &bitmap);

BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bi;

bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bitmap.bmWidth;
bi.biHeight = bitmap.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = 16;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
//std::cout<< bitmap.bmWidth;
DWORD dwBmpSize =((bitmap.bmWidth * bi.biBitCount + 5) / 32) * 4 * bitmap.bmHeight;
//int i = bitmap.bmWidth;
//DWORD dwBmpSize = 99;

HANDLE hDIB = GlobalAlloc(GHND, dwBmpSize);

char* bufptr = (char *)GlobalLock(hDIB);

GetDIBits(handle_ScreenDC, handle_Bitmap, 0, (UINT)bitmap.bmHeight, bufptr, (BITMAPINFO *)&bi, DIB_RGB_COLORS);


send(clientsock, bufptr , GlobalSize((char *)GlobalLock(hDIB)), 0);
/*Do i need to packetize/split it up? Or 1 send() is good for the matching Recv on the client?*/
/*I am assuming i must send bi structure over winsock also correct?*/

和接收客户端代码:

        case WM_PAINT:{

        //Im a Gdi beginner so I dont have a clue what im doing here as far as blitting the recved bits, this is just some stuff i tried myself before asking for help

        PAINTSTRUCT paintstruct;

        HDC handle_WindowDC = BeginPaint(hwnd, &paintstruct);

        handle_MemoryDC = CreateCompatibleDC(handle_WindowDC);


        handle_Bitmap = CreateCompatibleBitmap(handle_WindowDC, 640, 360);


         std::cout << SetDIBits(handle_MemoryDC, handle_Bitmap, 0, bi.biHeight, buffer, (BITMAPINFO *)&bi, DIB_RGB_COLORS);

        SelectObject(handle_MemoryDC, handle_Bitmap);

        StretchBlt(handle_WindowDC, 50, 50, 640, 360, handle_MemoryDC, 0, 0, x, y, SRCCOPY);


        EndPaint(hwnd, &paintstruct);

    }
4

1 回答 1

0

套接字在两端确实有有限的缓冲区大小,通常约为 4000 字节。因此,如果您在一次调用非阻塞发送时转储一大块数据(如全屏转储),您可能会遇到错误,并且您需要管理自己的缓冲区,调用多次发送。但是,如果您使用的是非阻塞套接字,则应该没问题,因为 send() 只会阻塞,直到发送所有数据。

在接收端,情况类似 - 阻塞接收可以一直等待,直到它具有您要求的完整数据大小,但非阻塞接收将返回当时可用的任何数据,这将导致在逐位过滤数据中,您将需要从多个 recv() 调用中重新组装数据。

我听说过一次发送非常大的数据块的问题,因此如果您一次发送 5 兆字节的数据,请注意可能还会出现其他问题。

于 2013-06-21T04:49:46.163 回答