使用 Winsock 远程控制 Windows Mobile 设备





5.00/5 (2投票s)
通过无线/有线连接远程控制您的移动设备,不基于 RAPI
引言
本文介绍了通过无线或有线远程控制 Windows Mobile 的实现方法。通过从移动设备获取屏幕截图并将其保存为压缩的 jpeg 文件,然后通过套接字发送。提供了一个桌面应用程序来显示通过套接字端口发送的文件图像。
背景
捕获移动屏幕或桌面屏幕是市场上所有远程应用程序的主要思路,这个思路很简单,只需捕获屏幕并将其发送到套接字,然后再将其发送到桌面应用程序。 我们可以按原样(作为 BMP)发送它,但我总是注意网络流量,因此在发送之前进行压缩。 您也可以基于本文构建一个在桌面上运行的客户端应用程序,而不是从移动客户端远程控制您的 PC,例如在您工作/大学/旅行等时。
您将从本文中受益:
- 您对 Windows Mobile 开发感兴趣。
- 您想了解如何在移动设备和桌面上使用套接字技术。
- 学习如何使用 Zlib 库压缩文件。
- 学习如何使用 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;
}
现在看看我的代码以创建线程函数来处理一些东西,祝您好运,我希望能够创建应用程序来帮助您在您的生活中。