65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Winsock 远程控制 Windows Mobile 设备

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2012年5月18日

CPOL

3分钟阅读

viewsIcon

27929

downloadIcon

1837

通过无线/有线连接远程控制您的移动设备,不基于 RAPI

 

引言

本文介绍了通过无线或有线远程控制 Windows Mobile 的实现方法。通过从移动设备获取屏幕截图并将其保存为压缩的 jpeg 文件,然后通过套接字发送。提供了一个桌面应用程序来显示通过套接字端口发送的文件图像。

背景

捕获移动屏幕或桌面屏幕是市场上所有远程应用程序的主要思路,这个思路很简单,只需捕获屏幕并将其发送到套接字,然后再将其发送到桌面应用程序。 我们可以按原样(作为 BMP)发送它,但我总是注意网络流量,因此在发送之前进行压缩。 您也可以基于本文构建一个在桌面上运行的客户端应用程序,而不是从移动客户端远程控制您的 PC,例如在您工作/大学/旅行等时。

您将从本文中受益:

  1. 您对 Windows Mobile 开发感兴趣。
  2. 您想了解如何在移动设备和桌面上使用套接字技术。
  3. 学习如何使用 Zlib 库压缩文件。
  4. 学习如何使用 wingdi API。

使用代码

  • 客户端 (移动应用程序)
  • 服务器端 (桌面应用程序)
//
wVersionRequested = MAKEWORD(2,0);
Status = WSAStartup (wVersionRequested, &wsaData);
	if (Status != 0) {
		ShowErr (TEXT("WSAStartup call failed!!, Error %d\r\n"), WSAGetLastError());
		return;
	}
//

1. 使用您可以在 Microsoft 中检查版本号的特定版本初始化 winsock2 库

应用程序版本

DLL 版本

wVersion 已请求

wVersion

wHigh 版本

结果

1.1

1.1

1.1

1.1

1.1

使用 1.1

1.0 1.1

1.0

1.1

1.0

1.0

使用 1.0

1.0

1.0 1.1

1.0

1.0

1.1

使用 1.0

1.1

1.0 1.1

1.1

1.1

1.1

使用 1.1

1.1

1.0

1.1

1.0

1.0

应用程序失败

1.0 1.1

1.0 1.1

1.1

1.1

1.1

使用 1.1

1.1 2.2

1.1

2.2

1.1

1.1

使用 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. 此函数创建一个绑定到特定服务提供商的套接字,如果您想通过 TCP 协议或 UDP 等连接...

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

3. 准备服务器套接字:我的意思是检测 IP 和端口号,然后您可以调用 connect 函数来尝试连接到此服务器。

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

} 

4-在成功创建与此服务器的连接后,我们想了解 GDI 函数,以了解我们如何获取屏幕截图。 查找以下内容

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

现在,正如我告诉你的,我们想压缩此捕获并将其放入低大小的 jpeg 文件中,我想在这里放置压缩代码,但如果您想了解如何进行物理压缩,请咨询 Zlib 库

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- 现在您可以自由地通过套接字在我们的代码中发送文件,您将找到线程函数来执行此操作,我将捕获保存为 jpg 文件,并在 Windows 目录中创建了一些代码来检查屏幕上是否有更改,因此无需再次发送文件

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

在讨论服务器端代码之前,我想让您了解一个重要的事情是什么? 我们如何将点击从服务器发送到移动设备,移动设备将如何处理它。

我认为您必须创建 SubClass 并捕获一些消息来做您想做的任何事情

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; 

 服务器端 : 

	//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;
	} 

现在看看我的代码以创建线程函数来处理一些东西,祝您好运,我希望能够创建应用程序来帮助您在您的生活中。

© . All rights reserved.