2013-05-03 83 views
0

我打算通過winsock發送桌面截圖。通過winsock發送位圖數據? Winapi

因此,有四項任務:

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一個字符數組。 將數據寫入服務器,我已經完成,但我有問題。 要將數據從服務器寫入客戶端,是否需要僅使用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?*/ 

和receiveing客戶端代碼:

 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); 

    } 

回答

0

套接字確實有兩端有限的緩衝區大小,通常約爲4000字節。因此,如果在一次調用非阻塞發送的過程中轉儲大塊數據(如完整的screendump),您可能會遇到錯誤,您將需要管理自己的緩衝區,調用多次發送。但是,如果您使用的是非阻塞套接字,則應該正常,因爲send()將會阻塞,直到發送完所有數據爲止。

在接收端,它是一個類似的情況 - 阻塞接收可以持續等待,直到它具有您要求的完整數據大小,但是非阻塞接收將返回當前可用的任何數據,這將導致數據逐位過濾,您將需要重新組合來自多個recv()調用的數據。

我聽說一次發送真正大塊數據的問題,所以如果你一次發送5兆字節的數據,請注意可能還會有其他問題發揮作用。