2013-05-03 4 views
0

winsock을 통해 데스크톱의 스크린 샷을 보내고 있습니다.winsock을 통해 비트 맵 데이터를 보내시겠습니까? Winapi

는 다음과 같은 네 개의 작업이 있습니다 :

내가 GetDIBits을 사용하여 char 배열에 비트 맵을 저장 한
Save bitmap to buffer 
Write data across wire using a socket 
Read data from wire using a socket 
Load a bitmap from a buffer 

. 데이터를 서버에 쓰면 끝났지 만 질문이 있습니다. 서버에서 클라이언트로 데이터를 쓰려면, 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 메가 바이트의 데이터를 보내는 경우 다른 문제도 발생할 수 있습니다.