This whole thread is for "help him with that attitude".
But if you could help him a little better than it had been done before - just do it!
Printable View
You did? Could you show the code? BTW, attaching zip with compilable project works much and much better than posting code snippets.
I did that. Your code is messy, and a good deal of your explanations sound kinda gibberish, "I did draw it from BITMAPINFO struct" definitely does. And I can see you're still not able to do what you want. Isn't that because you keep neglecting advices you are given with? I would say, aggressively neglecting. :)Quote:
only if u'd read whole thread...
Fine, it's up to you.Quote:
if I'd want to use MFC or ATL, I'd do it from the start
No it's not. Releasing DC never was equivalent to unselecting bitmap and releasing DC.Quote:
the closest function to release a bitmap is ReleaseDC, which I'm using in case u didn't notice
unfortunatelly I did not find a function to release bitmap, but I'm deleting it, so that's kinda fine, also Ill upload project for you, I hope MEGA isnt prohibited here, and also I tried to modify the code in the client, that instead of sending the buffer containing my header (command), bitmapinfo and data it will instead retrieve it the same way as the server does and display it, well, it wasnt so surprising that it worked, but the very same code doesnt work on the server side, therefore we can assume that there's something wrong between sockets, also I guess it's maybe because it processes like 100 messages when I send only one (only happens with data, when I send normal text string everything's fine), anyway I tried to force program to stop accepting messages after I obtain first bitmap, however, it DID draw bitmap occasionaly (i dont know why, but it did) BUT it did draw only bottom 1/3 of the bitmap (the drawn part of bitmap was correctly drawn), I will upload projects soon and edit this reply
edit: here's the link, please ignore the PathSocket lib source, since it was the first attempt of lib creation, so is this project, in the client, in WM_TIMER u have commented code that I used to retrieve the data from "data" vector, instead of sending it, sending code is under IDC_SEND, I'm sure u'll be able to put it together and see, that it actually retrieves and draws bitmap fine to the client, also, when starting a server, just select a port, n. of clients and start to listen, after that just click to that listbox and select "view screen", it draws received bitmap directly to there, so if u send it before you open it, u wont see anything, also the program isnt finished at all, but Im sure u won't get lost
https://mega.co.nz/#!2ghXTDLA!YjBu0z...Nrw2onNK-bNO6Y
As Igor mentioned, you should zip up your project and post it here as an attachment (remove unnecessary files such as *.obj., *.pdb, *.pch, *.exe, etc., and only have source files, any resource files, and of course the *.vcproj file, i.e. all files that are required for the project to build on another machine).
This way, everyone has the full code, and can run it, change it, debug it, etc. I only identified generic C/C++ errors in terms of buffer overruns and other issues, and that is only with the code you posted. The actual handling of the bitmap data in terms of GDI function calls and such requires much more analysis, and that can only be achieved if the whole code is seen in its entirety and can the issue duplicated on another machine.
But to add, one thing you don't do is that you don't check for errors in any of the GDI calls. I'm sure that some are returning error codes to you, but your code doesn't check for them (the error code, and if necessary, calls to GetLastError() to get more information). Many times, a black image is produced after GDI has informed your app of a failure (which your code doesn't take heed of).
Regards,
Paul McKenzie
well, now Im able to send, receive and draw the bitmap, but there are 2 more erros happening:
1. the bitmap on the server is weird, like, it changes colors and stuff, for example everythings pink, or yellow (but still shows actual bitmap, it just has weird colors) - looks fine on the client
2. the server after 10 sec crashes because of "std::bad_alloc" or just freezes
client capture & send code:
server receive & draw code:Code:RECT rc;
GetClientRect(GetDesktopWindow(), &rc);
HDC hDC = CreateCompatibleDC(NULL);
HBITMAP hBmp = CreateCompatibleBitmap(GetDC(NULL), 640, 360);
SelectObject(hDC, hBmp);
StretchBlt(hDC, 0, 0, 640, 360, GetDC(NULL), 0, 0, rc.right, rc.bottom, SRCCOPY);
//hBmp now contains screen image
//get bitmapinfo
BITMAPINFO bi;
memset(&bi, 0, sizeof(BITMAPINFO));
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
int a = GetDIBits(hDC, hBmp, 0, 1, NULL, &bi, DIB_RGB_COLORS);
if(a == 0)
return 0;
char *buff = new char[256*256*256];
a = GetDIBits(hDC, hBmp, 0, bi.bmiHeader.biHeight, buff, &bi, DIB_RGB_COLORS);
if(a == 0)
return 0;
char command[] = "bitmap_size";
char *data = new char[256*256*256];
int i = 0;
memcpy(data+i, &bi, sizeof(BITMAPINFO));
i += sizeof(BITMAPINFO);
memcpy(data+i, buff, bi.bmiHeader.biSizeImage);
i += bi.bmiHeader.biSizeImage;
char msg[128];
wsprintf(msg, "%s %d", command, i);
send(mySock, msg, strlen(msg), 0);
send(mySock, data, i, 0);
delete[] buff;
delete[] data;
ReleaseDC(hWnd, hDC);
DeleteDC(hDC);
DeleteObject(hBmp);
Code:int size;
if(bGotInfo && iBuffSize > 0)
size = iBuffSize;
else
size = 256;
vector<char> buff(size);
int re = recv((SOCKET)wParam, &buff[0], size, 0);
if(re <= 0) return 0;
char command[] = "bitmap_size";
int len = strlen(command);
if(strncmp(&buff[0], command, len) == 0)
{
char tmp[32];
strncpy_s(tmp, &buff[0]+len+1, re-len-1);
stringstream ss;
ss << tmp;
ss >> iBuffSize;
bGotInfo = true;
}
else if(bGotInfo)
{
int recvsize = re;
int a;
while(recvsize < iBuffSize)
{
a = recv((SOCKET)wParam, &buff[0]+recvsize, size, 0);
if(a > 0)
recvsize += a;
}
BITMAPINFO bi;
int i = 0;
memcpy(&bi, &buff[0], sizeof(BITMAPINFO));
i += sizeof(BITMAPINFO);
int imgSize = bi.bmiHeader.biSizeImage;
vector<BYTE> data(imgSize);
memcpy(&data[0], &buff[0+i], imgSize);
HDC hWindow = GetDC(hWnd);
HDC hDC = CreateCompatibleDC(hWindow);
HBITMAP hBmp = CreateCompatibleBitmap(hWindow, bi.bmiHeader.biWidth, bi.bmiHeader.biHeight);
SelectObject(hDC, hBmp);
SetDIBits(hDC, hBmp, 0, bi.bmiHeader.biHeight, &data[0], &bi, DIB_RGB_COLORS);
SetStretchBltMode(hWindow, HALFTONE);
StretchBlt(hWindow, 400, 0, 230, 200, hDC, 0, 0, bi.bmiHeader.biWidth, bi.bmiHeader.biHeight, SRCCOPY);
ReleaseDC(hWnd, hDC);
DeleteDC(hDC);
DeleteDC(hWindow);
DeleteObject(hBmp);
bGotInfo = false;
This is where you need to dump the bitmaps to files and inspect/compare them. I bet the RGB quad information is different on the server than on the client.
You're using many unsafe constructs in your code using char arrays (assuming they are "large enough" to hold the information), and making "off-by-1" errors in various places. Eventually you should be using a string class (std::string) and forego the char arrays.Quote:
2. the server after 10 sec crashes because of "std::bad_alloc" or just freezes
What if "a" is 256? I asked this previously about another instance of this error in another part of your code.Code:char buff[256];
int a = recv(mySock, buff, 256, 0);
buff[a] = '\0';
Last, your code is inefficent if you're going to keep calling new[]/delete[] with the very same dimensions (256*256*256). Either do it once and save the allocated data, or use vectors (much safer) and size them at the beginning of the program.
Regards,
Paul McKenzie
Here is an example in your server code of unsafe string handling:
You set the array size to 32, and then you're on a knife's edge with this by attempting to place characters that by definition, can exceed a length of 32 (the "Connected Clients: " string, plus the two integers). Instead, use streams, as they are much safer.Code:if(res == FD_ACCEPT || res == FD_CLOSE)
{
HWND hTmp = GetDlgItem(hWnd, IDC_CLIENTS);
char tmp[32];
wsprintf(tmp, "Connected Clients: %d/%d", ps->GetClients(), ServerInfo.sockets);
SendMessage(hTmp, WM_SETTEXT, NULL, (LPARAM)tmp);
}
Now there is no chance of a memory overwrite. If you insist on using arrays, make them able to hold 10,000 or so characters. Then you're safe up to 10,000 characters, reducing the chance of a memory overwrite.Code:std::ostringstream strm;
//...
if(res == FD_ACCEPT || res == FD_CLOSE)
{
HWND hTmp = GetDlgItem(hWnd, IDC_CLIENTS);
strm << "Connected Clients: " << ps->GetClients() << "/" << ServerInfo.sockets;
SendMessage(hTmp, WM_SETTEXT, NULL, (LPARAM)strm.str().c_str());
}
Regards,
Paul McKenzie
thanks! that \0 appending was changed on the server, but not on the client, anyway I know why it is causing bad_alloc; when I get bitmap_size message, it contains size of the array that's coming, e.g. bitmap_size 123456, however it is sometimes somehow (randomly, I even ran the server for like minute and nothing, on another try I got it after few seconds...) adding "(" at the end of the message - "bitmap_size 123456(" - that's why it is giving me bad alloc, I tried to find the "(" in the buffer and replace it with '\0', but without any success, im not sure why, I'd like to fix this first, before I go to try to fix the colors, any suggestions? also I made some changes to the code (imageBuff and imageData are global vectors), and yes, I tried to do receiving code with vector too - same result, bad colors & occasionaly "(" at the end
sending:
receiving:Code:RECT rc;
GetClientRect(GetDesktopWindow(), &rc);
HDC hDC = CreateCompatibleDC(NULL);
HBITMAP hBmp = CreateCompatibleBitmap(GetDC(NULL), 640, 360);
SelectObject(hDC, hBmp);
StretchBlt(hDC, 0, 0, 640, 360, GetDC(NULL), 0, 0, rc.right, rc.bottom, SRCCOPY);
BITMAPINFO bi;
memset(&bi, 0, sizeof(BITMAPINFO));
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
int a = GetDIBits(hDC, hBmp, 0, 1, NULL, &bi, DIB_RGB_COLORS);
if(a == 0)
return 0;
if(imageBuff.size() != bi.bmiHeader.biSizeImage)
imageBuff.resize(bi.bmiHeader.biSizeImage);
a = GetDIBits(hDC, hBmp, 0, bi.bmiHeader.biHeight, &imageBuff[0], &bi, DIB_RGB_COLORS);
if(a == 0)
return 0;
char command[] = "bitmap_size";
int size = sizeof(BITMAPINFO) + bi.bmiHeader.biSizeImage;
if(imageData.size() != size)
imageData.resize(size);
int i = 0;
memcpy(&imageData[0], &bi, sizeof(BITMAPINFO));
i += sizeof(BITMAPINFO);
memcpy(&imageData[0+i], &imageBuff[0], bi.bmiHeader.biSizeImage);
i += bi.bmiHeader.biSizeImage;
char msg[128];
wsprintf(msg, "%s %d", command, i);
Log(hWnd, msg);
send(mySock, msg, strlen(msg), 0);
send(mySock, &imageData[0], i, 0);
ReleaseDC(hWnd, hDC);
DeleteDC(hDC);
DeleteObject(hBmp);
Code:int size;
if(bGotInfo && iBuffSize > 0)
size = iBuffSize;
else
size = 256;
char *buff = new char[size];
int re = recv((SOCKET)wParam, buff, size, 0);
if(re <= 0) return 0;
if(re != size) buff[re] = '\0';
char command[] = "bitmap_size ";
int len = strlen(command);
if(strncmp(buff, command, len) == 0)
{
char tmp[32];
strncpy_s(tmp, buff+len, re-len);
stringstream ss;
ss << tmp;
ss >> iBuffSize;
Log(hWnd, buff);
bGotInfo = true;
}
else if(bGotInfo)
{
int recvsize = re;
int a;
while(recvsize < iBuffSize)
{
a = recv((SOCKET)wParam, buff+recvsize, size, 0);
if(a > 0)
recvsize += a;
}
BITMAPINFO bi;
memcpy(&bi, buff, sizeof(BITMAPINFO));
int i = sizeof(BITMAPINFO);
int imgSize = bi.bmiHeader.biSizeImage;
char *imageData = new char[imgSize];
memcpy(imageData, buff+i, imgSize);
HDC hWindow = GetDC(hWnd);
HDC hDC = CreateCompatibleDC(hWindow);
HBITMAP hBmp = CreateCompatibleBitmap(hWindow, bi.bmiHeader.biWidth, bi.bmiHeader.biHeight);
SelectObject(hDC, hBmp);
SetDIBits(hDC, hBmp, 0, bi.bmiHeader.biHeight, imageData, &bi, DIB_RGB_COLORS);
SetStretchBltMode(hWindow, HALFTONE);
StretchBlt(hWindow, 400, 0, 230, 200, hDC, 0, 0, bi.bmiHeader.biWidth, bi.bmiHeader.biHeight, SRCCOPY);
ReleaseDC(hWnd, hDC);
DeleteDC(hDC);
DeleteDC(hWindow);
DeleteObject(hBmp);
delete[] imageData;
bGotInfo = false;
}
delete[] buff;
}
The issue seems to be that you're using null-terminated strings, and at the same time, sending/receiving non-null terminated strings, and the two representations are conflicting with each other.
For a simple fix, terminate all of your strings with a NULL, and send the string plus the terminating NULL and expect the receiver to get a string plus terminating NULL. That means that the data, instead of being "abc123" will be "abc123\x0", i.e. 7 bytes, not 6 bytes. This also means that you eliminate code where you are appending a NULL on the received string as there will be no need to do so.
For the color issue, the problem is that your color information isn't correct. That's why you should take what you received and dump it to a file (don't just display it). Then inspect the bitmap with a hex editor and observe the bitmap information header plus the RGB data (plus palette if there is a palette). The bitmaps must compare exactly the same, -- you could even use a "diff" utility pointing out the differences in the file.
As to vector -- stick with using it. The vector protects you against everything (memory leaks, having to write buggy code to size a vector, etc.) -- except that you can still access memory outside the bounds of a vector. For example, if your vector can hold 10 elements, but you attempt to access the 11th element using operator [], you get no warning of this, no different than an array and your program may crash as a result.
Regards,
Paul McKenzie
okay, I'm now including null in the string before sending, this works fine, however Im still getting VS errors, here's output from client:
and here is sending code:Code:Incoming Buffer size: 921645
Total New: 103304
Total New: 921664
Received: 921664 - Image Size: 921600
Incoming Buffer size: 921645
Total New: 921446
Total New: 945910
and here's receiving code:Code:RECT rc;
GetClientRect(GetDesktopWindow(), &rc);
HDC hDC = CreateCompatibleDC(NULL);
HBITMAP hBmp = CreateCompatibleBitmap(GetDC(NULL), 640, 360);
SelectObject(hDC, hBmp);
StretchBlt(hDC, 0, 0, 640, 360, GetDC(NULL), 0, 0, rc.right, rc.bottom, SRCCOPY);
BITMAPINFO bi;
memset(&bi, 0, sizeof(BITMAPINFO));
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
int a = GetDIBits(hDC, hBmp, 0, 1, NULL, &bi, DIB_RGB_COLORS);
if(a == 0)
return 0;
if(imageBuff.max_size() != bi.bmiHeader.biSizeImage)
imageBuff.resize(bi.bmiHeader.biSizeImage);
a = GetDIBits(hDC, hBmp, 0, bi.bmiHeader.biHeight, &imageBuff[0], &bi, DIB_RGB_COLORS);
if(a == 0)
return 0;
int size = sizeof(BITMAPINFO) + bi.bmiHeader.biSizeImage + 1;
if(imageData.max_size() != size)
imageData.resize(size);
memcpy(&imageData[0], &bi, sizeof(BITMAPINFO));
int i = sizeof(BITMAPINFO);
memcpy(&imageData[0+i], &imageBuff[0], bi.bmiHeader.biSizeImage);
i += bi.bmiHeader.biSizeImage;
memcpy(&imageData[0+i], "\x0", 1);
i++;
char command[] = "bitmap_size";
char msg[128];
wsprintf(msg, "%s %d\x0", command, i);
if(i != size)
{
char tmp[32];
wsprintf(tmp, "ERR");
Log(hWnd, tmp);
}
send(mySock, msg, strlen(msg)+1, 0);
send(mySock, &imageData[0], i, 0);
ReleaseDC(hWnd, hDC);
DeleteDC(hDC);
DeleteObject(hBmp);
}
as you can see, it is receiving more data than it is supposed to (it is supposed to get 921645, but gets 921664 (19 more), this wont crash the program, but when it gets 945910, then it crashes, also the output on the client works only if I "pause" the server with those debug points (noticed this when I was looking for what is causing bad_alloc), otherwise the output is something like thisCode:int size;
if(bGotInfo)
size = iBuffSize;
else
size = 256;
vector<char> buff(size);
int re = recv((SOCKET)wParam, &buff[0], size, 0);
if(re == SOCKET_ERROR) return 0;
char command[] = "bitmap_size ";
int len = strlen(command);
if(strncmp(&buff[0], command, len) == 0)
{
char tmp[128];
strncpy_s(tmp, &buff[0]+len, re-len);
stringstream ss;
ss << tmp;
ss >> iBuffSize;
wsprintf(tmp, "Incoming Buffer size: %d\x0", iBuffSize);
send(ps.GetSocket(0), tmp, strlen(tmp)+1, 0);
bGotInfo = true;
}
else if(bGotInfo)
{
int recvsize = re;
int a;
vector<char> tmp(size);
char tmp2[128];
while(recvsize < size)
{
a = recv((SOCKET)wParam, &tmp[0], size, 0);
if(a != SOCKET_ERROR)
{
wsprintf(tmp2, "Total New: %d\x0", a + recvsize);
send(ps.GetSocket(0), tmp2, strlen(tmp2)+1, 0);
memcpy(&buff[0]+recvsize, &tmp[0], a);
recvsize += a;
}
}
BITMAPINFO bi;
memcpy(&bi, &buff[0], sizeof(BITMAPINFO));
int i = sizeof(BITMAPINFO);
wsprintf(tmp2, "Received: %d - Image Size: %d\x0", recvsize, bi.bmiHeader.biSizeImage);
send(ps.GetSocket(0), tmp2, strlen(tmp2)+1, 0);
int imgSize = bi.bmiHeader.biSizeImage;
vector<char> imageData(imgSize);
memcpy(&imageData[0], &buff[0]+i, imgSize);
HDC hWindow = GetDC(hWnd);
HDC hDC = CreateCompatibleDC(hWindow);
HBITMAP hBmp = CreateCompatibleBitmap(hWindow, bi.bmiHeader.biWidth, bi.bmiHeader.biHeight);
SelectObject(hDC, hBmp);
SetDIBits(hDC, hBmp, 0, bi.bmiHeader.biHeight, &imageData[0], &bi, DIB_RGB_COLORS);
SetStretchBltMode(hWindow, HALFTONE);
StretchBlt(hWindow, 400, 0, 230, 200, hDC, 0, 0, bi.bmiHeader.biWidth, bi.bmiHeader.biHeight, SRCCOPY);
ReleaseDC(hWnd, hDC);
DeleteDC(hDC);
DeleteDC(hWindow);
DeleteObject(hBmp);
bGotInfo = false;
}
}
any suggestions on how to fix that receiving of data? this is probably the same on the server side - when I send messages fast, they get mixed, or something, when I add a little sleep after all send(), the output on the client is normal, but still crashes, since it receives more data somehow, output with sleeps after send() commandsCode:Incoming Buffer size: 921645
Total New: 607004
l New: 836652
w: 885260
Incoming Buffer size: 921645
Total New: 49047
al New: 156679
ew: 230515
279123
31
otal New: 379811
New: 428419
: 477027
5635
al New: 654099
ew: 706179
758259
39
otal New: 862419
New: 911027
Total New: 921427
I got no idea what can be wrong :XCode:Incoming Buffer size: 921645
Total New: 27936
Total New: 52240
Total New: 101844
Total New: 176304
Total New: 225944
Total New: 300404
Total New: 350044
Total New: 424504
Total New: 474144
Total New: 548604
Total New: 623064
Total New: 672704
Total New: 747164
Total New: 796804
Total New: 893164
Total New: 943208
Nothing related to the code discussed here. Just the same functionality implemented my way. No third party libraries, no STL, just a pure Win32 API.
Attachment 32261