TCP socket Server: Render image on window

I'm working on a project and I'm a beginner in VC++.
I'm creating a TCP server that will receive a bitmap and will show it on window.
The motive is to receive the continuous images from a client and show them one by one on server window.

My code is:

#include <WinSock2.h>
#include <Windows.h>
#include <stdio.h>
#include <io.h>

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>


#pragma comment (lib, "ws2_32.lib")

#define IDC_EDIT_IN 101
//#define IDC_EDIT_OUT 102
//#define IDC_MAIN_BUTTON 103
#define WM_SOCKET 104
#define DEFAULT_BUFLEN 1024
PAINTSTRUCT ps;


int nPort=5552;
HBITMAP hbitmap;
BITMAP cBitmap;
/*HWND hEditIn=NULL;
HWND hEditOut=NULL*/;
SOCKET Socket=NULL;
char szHistory[10000];
sockaddr sockAddrClient;

LRESULT CALLBACK WinProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR lpCmdLine,int nShowCmd)
{
WNDCLASSEX wClass;
ZeroMemory(&wClass,sizeof(WNDCLASSEX));
wClass.cbClsExtra=NULL;
wClass.cbSize=sizeof(WNDCLASSEX);
wClass.cbWndExtra=NULL;
wClass.hbrBackground=(HBRUSH)COLOR_WINDOW;
wClass.hCursor=LoadCursor(NULL,IDC_ARROW);
wClass.hIcon=NULL;
wClass.hIconSm=NULL;
wClass.hInstance=hInst;
wClass.lpfnWndProc=(WNDPROC)WinProc;
wClass.lpszClassName="Window Class";
wClass.lpszMenuName=NULL;
wClass.style=CS_HREDRAW|CS_VREDRAW;


if(!RegisterClassEx(&wClass))
{
int nResult=GetLastError();
MessageBox(NULL,
"Window class creation failed\r\nError code:",
"Window Class Failed",
MB_ICONERROR);
}


HWND hWnd=CreateWindowEx(NULL,
"Window Class",
"Capture Server",
WS_OVERLAPPEDWINDOW,
200,
200,
640,
480,
NULL,
NULL,
hInst,
NULL);


if(!hWnd)
{
int nResult=GetLastError();

MessageBox(NULL,
"Window creation failed\r\nError code:",
"Window Creation Failed",
MB_ICONERROR);
}


ShowWindow(hWnd,nShowCmd);

MSG msg;
ZeroMemory(&msg,sizeof(MSG));

while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return 0;


}



LRESULT CALLBACK WinProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)

{switch(msg)
{
case WM_COMMAND:
switch(LOWORD(wParam))
{

}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd,&ps);

if(hbitmap != 0)
{
HDC hdcMem = CreateCompatibleDC(hdc);

SelectObject(hdcMem, hbitmap);

BitBlt(hdc, 10, 10, cBitmap.bmWidth, cBitmap.bmHeight, hdcMem, 0, 0, SRCCOPY);

}

EndPaint (hWnd, &ps);

}

break;


case WM_CREATE:
{
ZeroMemory(szHistory,sizeof(szHistory));

// Create incoming message box
/*hEditIn=CreateWindowEx(WS_EX_CLIENTEDGE,
"EDIT",
"",
WS_CHILD|WS_VISIBLE|ES_MULTILINE|
ES_AUTOVSCROLL|ES_AUTOHSCROLL,
20,
20,
200,
20,
hWnd,
(HMENU)IDC_EDIT_IN,
GetModuleHandle(NULL),
NULL);*/
/*if(!hEditIn)
{
MessageBox(hWnd,
"Could not create incoming edit box.",
"Error",
MB_OK|MB_ICONERROR);
}*/

HGDIOBJ hfDefault=GetStockObject(DEFAULT_GUI_FONT);
/*SendMessage(hEditIn,
WM_SETFONT,
(WPARAM)hfDefault,
MAKELPARAM(FALSE,0));*/
/*SendMessage(hEditIn,
WM_SETTEXT,
NULL,
(LPARAM)"Waiting for client to connect...");*/




WSADATA WsaDat;
int nResult=WSAStartup(MAKEWORD(2,2),&WsaDat);
if(nResult!=0)
{
MessageBox(hWnd,
"Winsock initialization failed",
"Critical Error",
MB_ICONERROR);
SendMessage(hWnd,WM_DESTROY,NULL,NULL);
break;
}

Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(Socket==INVALID_SOCKET)
{
MessageBox(hWnd,
"Socket creation failed",
"Critical Error",
MB_ICONERROR);
SendMessage(hWnd,WM_DESTROY,NULL,NULL);
break;
}



SOCKADDR_IN SockAddr;
SockAddr.sin_port=htons(nPort);
SockAddr.sin_family=AF_INET;
SockAddr.sin_addr.s_addr=htonl(INADDR_ANY);

if(bind(Socket,(LPSOCKADDR)&SockAddr,sizeof(SockAddr))==SOCKET_ERROR)
{
MessageBox(hWnd,"Unable to bind socket","Error",MB_OK);
SendMessage(hWnd,WM_DESTROY,NULL,NULL);
break;
}


nResult=WSAAsyncSelect(Socket,
hWnd,
WM_SOCKET,
(FD_CLOSE|FD_ACCEPT|FD_READ));
if(nResult)
{
MessageBox(hWnd,
"WSAAsyncSelect failed",
"Critical Error",
MB_ICONERROR);
SendMessage(hWnd,WM_DESTROY,NULL,NULL);
break;
}



if(listen(Socket,(1))==SOCKET_ERROR)
{
MessageBox(hWnd,
"Unable to listen!",
"Error",
MB_OK);
SendMessage(hWnd,WM_DESTROY,NULL,NULL);
break;
}
}
break;

case WM_DESTROY:
{
PostQuitMessage(0);
shutdown(Socket,SD_BOTH);
closesocket(Socket);
WSACleanup();
return 0;
}
break;


case WM_SOCKET:
{
switch(WSAGETSELECTEVENT(lParam))
{
case FD_READ:
{
/*char szIncoming[1024];*/
char recvbuffer[102400];
int filebuflen = DEFAULT_BUFLEN;
ZeroMemory(recvbuffer, filebuflen);
int bytes_read = recv(Socket, recvbuffer, filebuflen, 0 );
/* ZeroMemory(szIncoming,sizeof(szIncoming));*/

/*int inDataLength=recv(Socket,
(char*)szIncoming,
sizeof(szIncoming)/sizeof(szIncoming[0]),
0);*/

/*strncat(szHistory,szIncoming,inDataLength);
strcat(szHistory,"\r\n");*/

/*SendMessage(hEditIn,
WM_SETTEXT,
sizeof(szIncoming)-1,
reinterpret_cast<LPARAM>(&szHistory));*/
if(bytes_read==0)
/* MessageBox(hWnd,
"File Read Error",
"Corrupt File",
MB_ICONINFORMATION|MB_OK);*/
break;
if(bytes_read <0)
{
MessageBox(hWnd,
"File Read Error",
"Corrupt File",
MB_ICONINFORMATION|MB_OK);
}


std::ifstream is;
char* pbuffer;
/*is.open("image.bmp", std::ios::binary);*/
/*is.seekg(0, std::ios::end);
*/




/* pbuffer = new char[bytes_read];*/
bytes_read = is.tellg();
/* is.seekg(0, std::ios::beg);*/
pbuffer = new char[bytes_read];
is.read(pbuffer, bytes_read);

is.close();
tagBITMAPFILEHEADER bfh = *(tagBITMAPFILEHEADER*)pbuffer;
tagBITMAPINFOHEADER bih = *(tagBITMAPINFOHEADER*)(pbuffer+sizeof(tagBITMAPFILEHEADER));

RGBQUAD rgb = *(RGBQUAD*)(pbuffer+sizeof(tagBITMAPFILEHEADER)+sizeof(tagBITMAPINFOHEADER));


BITMAPINFO bi;
bi.bmiColors[0] = rgb;
bi.bmiHeader = bih;
char* pPixels = (pbuffer+bfh.bfOffBits);

char* ppvBits;


hbitmap = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, (void**) &ppvBits, NULL, 0);
SetDIBits(NULL, hbitmap, 0, bih.biHeight, pPixels, &bi, DIB_RGB_COLORS);

GetObject(hbitmap, sizeof(BITMAP), &cBitmap);
delete[] pbuffer;
/*infile = fopen("test.txt","wb");
fwrite (filebuf, 1, sizeof(filebuf), infile);
fclose (infile);*/

}
break;

case FD_CLOSE:
{
MessageBox(hWnd,
"Client closed connection",
"Connection closed!",
MB_ICONINFORMATION|MB_OK);
/*closesocket(Socket);*/
SendMessage(hWnd,WM_DESTROY,NULL,NULL);
}
break;
case FD_ACCEPT:
{
int size=sizeof(sockaddr);
Socket=accept(wParam,&sockAddrClient,&size);
if (Socket==INVALID_SOCKET)
{
int nret = WSAGetLastError();
WSACleanup();
}
/*SendMessage(hEditIn,
WM_SETTEXT,
NULL,
(LPARAM)"Client connected!");*/
}
break;
}
}
}

return DefWindowProc(hWnd,msg,wParam,lParam);


}


and I'm getting an error. when client is sending the image then it is completely sent from client side but I can't see it on server side.

Help me Please.
Thanks!
That's unbelievably hard to read, especially since half of it appears to be commented out.

I'd suggest three things before you're likely to get any help.

1) Use code tags
2) Indent properly
3) Post only the relevant code
Last edited on
the problem is that you don't get the whole image with a single call to recv.

How much data you get with a single call to recv depends on the buffer of the socket not the buffer you provide.
@ihutch, Thats my mistake..
to read on socket my code is..
case WM_SOCKET:
{
switch(WSAGETSELECTEVENT(lParam))
{
case FD_READ:
{

char recvbuffer[102400];
int filebuflen = DEFAULT_BUFLEN;
ZeroMemory(recvbuffer, filebuflen);
int bytes_read = recv(Socket, recvbuffer, filebuflen, 0 );

if(bytes_read==0)

break;
if(bytes_read <0)
{
MessageBox(hWnd,
"File Read Error",
"Corrupt File",
MB_ICONINFORMATION|MB_OK);
}


std::ifstream is;
char* pbuffer;





/* pbuffer = new char[bytes_read];*/
bytes_read = is.tellg();
/* is.seekg(0, std::ios::beg);*/
pbuffer = new char[bytes_read];
is.read(pbuffer, bytes_read);

is.close();
tagBITMAPFILEHEADER bfh = *(tagBITMAPFILEHEADER*)pbuffer;
tagBITMAPINFOHEADER bih = *(tagBITMAPINFOHEADER*)(pbuffer+sizeof(tagBITMAPFILEHEADER));

RGBQUAD rgb = *(RGBQUAD*)(pbuffer+sizeof(tagBITMAPFILEHEADER)+sizeof(tagBITMAPINFOHEADER));


BITMAPINFO bi;
bi.bmiColors[0] = rgb;
bi.bmiHeader = bih;
char* pPixels = (pbuffer+bfh.bfOffBits);

char* ppvBits;


hbitmap = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, (void**) &ppvBits, NULL, 0);
SetDIBits(NULL, hbitmap, 0, bih.biHeight, pPixels, &bi, DIB_RGB_COLORS);

GetObject(hbitmap, sizeof(BITMAP), &cBitmap);
delete[] pbuffer;


}
break;


I'm not getting on how to show this on window.
@coder777,,,

That may be an issue with app..
Do you have any idea to overcome this problem??
On the sender side I suggest to transmit the size of the image first.
On the receiver side use that to allocate the required buffer size on the heap (100 k might even not be enough). Then recv in a loop until the data is received (or an error occurs). You need an offset in your buffer where the next data can be stored.

There's a problem: your gui will freeze until the whole image is received.
I got stuck in this so I tried this approach:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
int i=256;
			BYTE* data = new BYTE[256*i];
  int packetsize, num;
  int newWidth, newHeight;
  int recvimgsize=0;

   bool bAwaitingImage = false;
			switch(WSAGETSELECTEVENT(lParam))
			{
				case FD_READ:
				{
					  num=recv(Socket, (char*)data, 16, 0);
				
				if(num>0)
      {

		  for(int i=0; i<32; i++)
		  {
        packetsize = data[i]*256+ data[i];

        num=recv(Socket, (char*)(data+16), packetsize-16, 0);
      }
				}
				 if(num>0)
				 {
				 switch(data[0])
				 {
				  case 2: //received information about window size (image size)

					  for(int i=0; i<16; i++)
					  {
            newWidth = data[i]*256+data[i];
            newHeight = data[i]*256+data[i];
					  } 		 



but when client starts sending the data server hangs and stops working..
This looks extremely difficult.

1
2
3
4
5
6
7
		  for(int i=0; i<32; i++) // You received 16 bytes, why this 32?
		  {
        packetsize = data[i]*256+ data[i]; // I don't understand this calculation

        num=recv(Socket, (char*)(data+16), packetsize-16, 0); // you store the received data alsways at the same location. I.e. it's overwritten the next iteration
// you don't care whether data is received or not?
      }


Is your socket blocking? If so and if no more data is available it will freeze you program until data is available. Or is async always non blocking?
Actually the main calculation is...


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

			BYTE* data = new BYTE[256*256*256];
  int packetsize, num;
  int newWidth, newHeight;
  int recvimgsize=0;

   bool bAwaitingImage = false;
			switch(WSAGETSELECTEVENT(lParam))
			{
				case FD_READ:
				{
	
					  num=recv(Socket, (char*)data, 3, 0);
				
				if(num>0)
      {

		
        packetsize = data[1]*256+ data[2];

        num=recv(Socket, (char*)(data+3), packetsize-3, 0);
     
				}
				 if(num>0)
				 {
				 switch(data[0])
				 {
				  case 2: //received information about window size (image size)

					 
            newWidth = data[3]*256+data[4];
            newHeight = data[5]*256+data[6];
					


But its not having anything...
The problem is that you might not get the expected amount of bytes.

if you write

1
2
num=recv(Socket, (char*)(data+3), packetsize-3, 0);
// I would have understood datasize-3, but why packetsize-3? 


num != packetsize-3 might very well be they case. It is not guaranteed that you get size you expect!

async is a bit inconvenient: if you get less than expected you need to wait for the next event to get the rest (this might be as well less then expected...)
I'm receiving the bytes,,thats ok but I think there is some problem in creating bitmap..
its my code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
static char buff[MAX_SIZE];
					int num;
					 
          num=recv(Socket, buff, sizeof(buff), 0);

		 
    // progress the buffer
  

	
	strncat(szHistory,  buff , num );
					strcat(szHistory,"\r\n");

					SendMessage(hWnd,
						WM_SETTEXT,
						sizeof(num)-1,
						reinterpret_cast<LPARAM>(&szHistory));
					if(SendMessage)
					{

					std::ifstream is;

					is.open(buff, std::ios::binary);
					is.seekg(0, std::ios::end);
					num = is.tellg();
					is.seekg(0, std::ios::beg);
					 

					
					is.read(buff, num);

					tagBITMAPFILEHEADER bfh = *(tagBITMAPFILEHEADER*)buff;
					tagBITMAPINFOHEADER bih = *(tagBITMAPINFOHEADER*)(buff+sizeof(tagBITMAPFILEHEADER));

					RGBQUAD             rgb = *(RGBQUAD*)(buff+sizeof(tagBITMAPFILEHEADER)+sizeof(tagBITMAPINFOHEADER));


					BITMAPINFO bi;
bi.bmiColors[0] = rgb;
bi.bmiHeader = bih;
char* pPixels = (buff+bfh.bfOffBits);

char* ppvBits;


hbitmap = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, (void**) &ppvBits, NULL, 0);
SetDIBits(NULL, hbitmap, 0, bih.biHeight, pPixels, &bi, DIB_RGB_COLORS);

GetObject(hbitmap, sizeof(BITMAP), &cBitmap);
	
 
					} 



Please suggest your answers.

Thanks!
I'd suggest using CreateDIBitmap:

http://msdn.microsoft.com/en-us/library/windows/desktop/dd183491%28v=vs.85%29.aspx

that seems to be easier.

Btw you cannot use BITMAPINFO like that. The bmiColors is supposed to contain all colors. So you need to create memory that holds BITMAPINFOHEADER + all RGBQUAD (not just one) then cast it to a pointer to BITMAPINFO for CreateDIBSection
Topic archived. No new replies allowed.