Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Remote windows mobile Device Using Winsock

0.00/5 (No votes)
18 May 2012 1  
Server Application to remote your mobile device through wireless/wire connection not based on RAPI

 

Introduction

This article describes the implementation of a remote Windows Mobile through wirleless or wire. by taking snapeshot screen from mobile and save it as compressed jpeg file ,then send it by socket. A desktop application is provided to display the file's image which sent it over socket port . 

Background

Capturing mobile screen or desktop screen is the main idea for all remote application sold in market, the idea it's too easy just capture the screen and send it to socket to sent it to desktop application. We can send it as-is (as a BMP but I am always careful about network trafic so I compess it before sending. You can also build a client application to run on the desktop based on this Article instead of from a Mobile Client to remote to your PC while you in work /University /trip etc.

You Will Benefit from this Article: 

  1. You’re interested in Windows mobile development.
  2. You would like to see how to use socket technology on mobile and desktop.
  3. learn how to compress file by Zlib library.
  4. learn how to use wingdi API. 

Using the code

  • Client Side (mobile application)
  • Server Side (Desktop application) 
//
wVersionRequested = MAKEWORD(2,0);
Status = WSAStartup (wVersionRequested, &wsaData);
	if (Status != 0) {
		ShowErr (TEXT("WSAStartup call failed!!, Error %d\r\n"), WSAGetLastError());
		return;
	}
//

1. Initialize the winsock2 Library with specific version you can check version Number From Microsoft  

Application version

DLL version

wVersion requested

wVersion

wHigh version

Result

1.1

1.1

1.1

1.1

1.1

use 1.1

1.0 1.1

1.0

1.1

1.0

1.0

use 1.0

1.0

1.0 1.1

1.0

1.0

1.1

use 1.0

1.1

1.0 1.1

1.1

1.1

1.1

use 1.1

1.1

1.0

1.1

1.0

1.0

Application fails

1.0 1.1

1.0 1.1

1.1

1.1

1.1

use 1.1

1.1 2.2

1.1

2.2

1.1

1.1

use 1.1 

        Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);

	if ( Sock == INVALID_SOCKET )
	{
		MessageBox(TEXT("Error: failed to create socket\n"),MB_OK);
		fflush(0);
		return ;
	} 

2. This function creates a socket that is bound to a specific service provider, if you want to connect through TCP Protocol or UDP  etc... 

	m_ServerSockAddr.sin_addr.s_addr=dwIPAddress;
	m_ServerSockAddr.sin_family=AF_INET;
	m_ServerSockAddr.sin_port=htons(987);  

3. Prepare Server Socket : I mean detect which IP and Port Number then you can call the connect function to try connect on this Server. 

//This function is used to create a connection to the specified destination
if ( connect( Sock, (SOCKADDR*) &m_ServerSockAddr, sizeof(m_ServerSockAddr) ) == SOCKET_ERROR)
{

} 

4-After Create success Connection with this Server We want to take tour in GDI function to know how how we can take Capture Screen. look for below 

HDC hdcScreen  = CreateDC(L"DISPLAY", NULL, NULL, NULL);

  HDC hdcCapture = CreateCompatibleDC(hdcScreen);

  int nWidth     = GetDeviceCaps(hdcScreen, HORZRES),

      nHeight    = GetDeviceCaps(hdcScreen, VERTRES),

      nBPP       = GetDeviceCaps(hdcScreen, BITSPIXEL);


  LPBYTE lpCapture;

  BITMAPINFO bmiCapture = { {

      sizeof(BITMAPINFOHEADER), nWidth, -(nHeight), 1, 24, BI_RGB, 0, 0, 0, 0, 0,

  } };

  HBITMAP hbmCapture = CreateDIBSection(hdcScreen, &bmiCapture,

      DIB_RGB_COLORS, (LPVOID *)&lpCapture, NULL, 0);

  
  int nCapture = SaveDC(hdcCapture);

  SelectObject(hdcCapture, hbmCapture);
  StretchBlt(hdcCapture, 0, 0, (nWidth), (nHeight),hdcScreen, 0, 0,nWidth, nHeight, SRCCOPY);

  //BitBlt(hdcCapture, 0, 0, nWidth, nHeight, hdcScreen, 0, 0, SRCCOPY);

  RestoreDC(hdcCapture, nCapture);

  DeleteDC(hdcCapture);

  DeleteDC(hdcScreen);

  int nResult = SaveFileJPEG(lpszFilename, nQuality, (JSAMPLE *)lpCapture, nWidth, nHeight);

  DeleteObject(hbmCapture); 

Now as I told you we want to compress this Capture and put it inside jpeg file with low size I want to put compress code here but it you want to learn how compress physically consult with Zlib Library   

SaveFileJPEG(char *filename, int quality, JSAMPLE *buffer, int width, int height) 
{
  struct jpeg_compress_struct jcompress;

  struct jpeg_error_mgr jerror;

  JSAMPROW scanline[1];

  FILE *outfile;

   

  memset(&jcompress, 0, sizeof(jcompress));

  memset(&jerror, 0, sizeof(jerror));

  jcompress.err = jpeg_std_error(&jerror);



  jpeg_create_compress(&jcompress);

  outfile = fopen(filename, "wb");

  if(!outfile) return 1;

  jpeg_stdio_dest(&jcompress, outfile);

   

  jcompress.image_width      = width;

  jcompress.image_height     = height;

  jcompress.input_components = 3;

  jcompress.in_color_space   = JCS_RGB;

  jpeg_set_defaults(&jcompress);

  jpeg_set_quality(&jcompress, quality, TRUE);

  jpeg_start_compress(&jcompress, TRUE);

   

  int nStride = width * 3;

  int nSize = nStride * height;

  for(int i = 2; i < nSize; i += 3){

      unsigned char nTemp = buffer[i - 2];

      buffer[i - 2] = buffer[i];

      buffer[i] = nTemp;

  }

  while(jcompress.next_scanline < height){

      scanline[0] = buffer;

      jpeg_write_scanlines(&jcompress, scanline, 1);

      buffer += nStride;

  }

   

  jpeg_finish_compress(&jcompress);

  jpeg_destroy_compress(&jcompress);

  fclose(outfile);

  return 0;

} 

 5- Now you are free to send file though socket inside our code you will found Thread Function to do that i saved the capture as jpg File inside windows Directory made some code to check if no change on screen so no need to send file again 

	pThis->GetScreeny("\\Windows\\1.jpeg", 20);
		CFile bmpFile(L"\\Windows\\1.jpeg", CFile::typeBinary | CFile::modeRead);
		char *bmpBuf;
		unsigned int fileLen = bmpFile.GetLength();
		/*
		here i just check if the file change or not
		*/
		if (fileLen!=oldFileSize)
		{
			oldFileSize=fileLen;
			bmpBuf = new char[fileLen];
			bmpFile.Read(bmpBuf,fileLen);
			DWORD nBytestoSend=sizeof(MESSAGEHEAD);
			m_msgHead.nImageFileSize=fileLen;
			// i send the file size before send file
			send(Sock, (char*)&m_msgHead, nBytestoSend, 0);
			int nSend=send(Sock, bmpBuf, fileLen, 0);
		
		} 

Before we going to Discuss Server Side Code i want to let you now about important thing what is it ? how we can send click from Server to mobile and the mobile will handle it.

I think you have to Create SubClass and catch some of message to do what ever you want 

case WM_KEYDOWN:
case WM_KEYUP:
case WM_SYSKEYUP:
case WM_SYSKEYDOWN:
// you can send event from server and got it through Recv function
if (recv (Sock, (char *)MouseData, sizeof(USHORT), 0) == sizeof(USHORT)) {
dwFlags = ((WM_KEYUP == Cmd) || (WM_SYSKEYUP == Cmd)) ? KEYEVENTF_KEYUP : 0;
// No scancode data.
keybd_event ((BYTE)MouseData[0], 0, dwFlags, 0);
}
break; 

 Server Side : 

	//Initialize the WinSock Stuff...
	/*1*/WORD VersionRequested = MAKEWORD(2,2);
	WSADATA wsaData;
	WSAStartup(VersionRequested, &wsaData);	// Start Winsock Service
	if ( wsaData.wVersion != VersionRequested )
	{
		MessageBox(TEXT("Wrong version or WinSock not loaded\n"),MB_OK);
		fflush(0);	
	}
	/*2*///create socket function we disucs what this function mean
	m_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if ( m_Socket == INVALID_SOCKET )
	{
		MessageBox(TEXT("Error: failed to create socket\n"),MB_OK);
		fflush(0);
		return false;
	}
	/*3*///To Crate Socket listen from any Client you can change it, by detect IP
	m_ServerSockAddr.sin_family = AF_INET;
	m_ServerSockAddr.sin_addr.s_addr = htonl( INADDR_ANY );	
	m_ServerSockAddr.sin_port = htons(987);

	BOOL temp;
	int len=sizeof(BOOL);
	int hr;
	/*4-
	This function is used on an unconnected socket before subsequent calls to the connect or listen function. The bind function is used to bind to either connection-oriented (stream) or connectionless (datagram) sockets. When a socket is created with a call to the socket function, it exists in a name space (address family) but has no name assigned to it. Use the bind function to establish the local association of the socket by assigning a local name to an unnamed socket.
	*/
	if ( bind( m_Socket, (struct sockaddr *)&m_ServerSockAddr, sizeof(m_ServerSockAddr)) != 0 )
	{
		MessageBox(TEXT("Error: failed to bind\n"),MB_OK);
		closesocket( m_Socket );
		return false;
	}
	/* 5
	This function places a socket at a state where it is listening for an incoming connection.
	*/
	if ( listen(m_Socket,SOMAXCONN) != 0)
	{
		MessageBox(TEXT("Error: failed to Listen\n"),MB_OK);
		closesocket( m_Socket );
		return false;
	} 

Now take tour inside my code  to Create Thread Function to handle some stuff gook luck and I wish to be able how create application to help you in your life. 

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here