家里没有无线路由器,幸亏有无线网卡,在东屋电脑主机上通过无线网卡共享WIFI,晚上要用WIFI,每次睡前都要到东屋去关电脑,感觉有些麻烦,之后冒出了一个想法:写一个遥控程序,遥控关电脑、监控电脑屏幕等,这样动动手指头,电脑就关了,以后就不麻烦了。
当然,本文主要对局域网控制技术进行研究,讲解如何通过Android手机遥控电脑关机锁屏等,其他远控功能不做重点研究。传统意义的远程控制一般指在一台PC上能操控另一台PC,而现在我们可以通过Android来达到远程控制PC效果。这里为达到遥控的效果,将采用局域网通信的原理来实现这一功能。本次本着求知的理念,打破传统PC作为服务端的思想,以Android手机作为服务端,PC作为客户端实现这一功能。
编程分析
Socket又称“套接字”,应用程序通常通过套接字向网络发出请求或者应答网络请求。
Socket是对TCP/IP协议的封装和应用,要传输数据则需TCP、UDP协议,TCP和UDP的概念很清楚:TCP建立连能中断,但中断后必须三次握手才能再建立连接,而UDP是可以再中断的。
TCP建立连接后,以后的发送不需要再指定IP等信息,而UDP每次都需要IP加端口,
所以UDP很适合手机控制电脑的操作,中间连接偶尔中断了也没事。我们要对Andorid端的事件监听,比如点击、双击、发送命令等各种事件,需要建立Socket,传递命令数据给客户端,同时实时监听客户端传来的消息。
客户端监听信息。有数据达到则进行数据识别,通过C++调用Windows的一些事件,这里指执行关机、锁屏等各种命令。Socket通信整个流程处理如图1所示。
Android控制电脑可用Socket来实现,Socket用来描述IP地址和端口。通过socket在局域网内实现控制电脑关机,其机理与Windows上实现socket通信一样,Android服务器端做如下流程处理:
1:创建服务器端套接字并绑定到一个端口上;
2:套接字设置监听模式,等待连接请求;
3:接受连接请求后进行通信,创建线程收发消息;
4:发送远控消息。
PC客户端编程思路如下:
1:初始化SOCKET;
2:连接服务器端;
3:创建线程收发消息并执行。
代码分析
1)服务器端核心代码分析
第一步:自定义函数获取本机IP。
Enumeration定义了一个名为nextElement的方法,可以从含多个元素的数据结构中得到的下一个元素,通过getNetworkInterfaces方法来获取本机所有的网络接口。NetworkInterface此类表示一个IP地址列表组成的网络接口。而InetAddress的实例对象包含以数字形式保存的IP地址,就是这么回事了。
publicStringgetLocalIpAddress() { try{ for (EnumerationNetworkInterface en = = NetworkInterface.getNetworkIces();en.hasMoreElements();) { NetworkInterfaceintf=en.nextElement(); for (EnumerationInetAddress enumIpAddr intf.getInetAddresses();enumIpAddr.hasMoreElements();) { InetAddressinetAddress=enumIpAddr.nextElement(); { { recvMessageServer += 请连接IP: +inetAddresstAddress()+: +serverSocket.getLocalPort()+\n; } } } } } catch(SocketExceptionex){ recvMessageServe+ex.getMessage()+\n; //消息换行 Messagemsg=newMessage(); msg.what=0; mHandler.sendMessage(msg); } Messagemsg=newMessage(); msg.what=0; mHandler.sendMessage(msg); returnnull; }
第二步:创建套接字,绑定端口,收发数据,在线程中完成。
privateRunnable mcreateRunnable publicvoidrun() try{ =newRunnable() { { serverSocket=newServerSocket(0); SocketAddre=null; if(!serverSocket.isBound()) { serverSocket.bind(address,0); } getLocalIpAddress(); //方法用于等待客服连接 mSocketServer=serverSocket.accept(); //接受客服端数据BufferedReader对象 mBufferedReaderServer=new BufferedReader(new InputStreamReader(mSocketServer.getInputStream())); mPrintWriterServer=newPrintWriter(mSocketServer.getOutputStream(),true); mPrintWriter.println(服务端已经收到数据);}}
2)客户端核心代码分析
第一步:初始化SOCKET。
WORDwVersionrequested; WSADATAwsaData; wVersuested=MAKEWORD(2,0); interr=WSAStartup(wVersionrequested,wsaData); if(err==-1) { MessageBox(0,WSAStartuperr,error,MB_OK);}
第二步:连接服务器。
char server_address[50]={0}; char recv_message_client[256]={0}; sockaddr_inserver_ip; struct SOCKETclientSockConnect; u_shortport; clientSock=socket(AF_INET,SOCK_STREAM,0); char*srstr(server_address,:); //Connect server_ip.sin_family=AF_INET; server_ip.sin_port=((port0xff00)8)|((port0x00ff)8); server_ip.sin_addr.S_un.S_addr=inet_addr(server_address); clientSockConnect=connect(clientSock,(structsockaddr*)server_ip,sizeof(server_ip)); if(clientSockConnect!=0) { CStringtemp; returnFALSE; }
第三步:在线程函数里设置监听收发信息,消息解析收到相应消息执行命令。
在连接按钮里添加创建线程的的代码:
hThread=CreateThread(NULL, 0, clientThreadFunc, NULL,//传递的参数 0, clientThreadID); 在线程函数里设置监听收发信息: DWORDWentThreadFunc(LPVOIDthreadNum) { while(clientThreadRun) { if((length=recv(clientSock,(char*)recv_message_client,sizeof(recv_message_client),0))0) { temp.Format(接收到的信息:\n%s,recv_message_client); SetDlgItemText(FindWindow(NULL, WINDOWNHANDLERNAME), IDC_STATIC,temp); memset(recv_message_client,0,sizeof(recv_message_client)); if(strcmp(recv_message_client,cmd)){ system(rundll32.exeuser32.dll,LockWorkStation);} } //system(rundll32.exeuser32.dll,LockWorkStation); temp.Format(接收到的信息:\n%s,recv_message_client); } return0;}
测试截图
图2是服务器端打开后的效果图,看到IP和端口后,我们开始连接。图3是客户端连接上的运行截图。
本程序分为客户端与服务端,服务端为控制端,客户端是PC上的应用程序,可以实现用Android手机控制电脑锁定,也可以略加代码执行关机打开应用等多种功能。总而言之,本程序是个框架,在其上挂什么衣服就可以呈现不同效果,只需加上几行代码。只要手机与网内,就可以实现这一功能。另外,通过这次编程学习,也学到了不少的知识。
当然,基于同样的SOCKET通信原理,我们还可以实现其他Android控制PC的功能,如屏幕实时监控,控制音量,打开某个网站,获取电脑中的某些文件,控制鼠标操作等等。
本文讲述的技术仍是一个框架,关键是基于如此框架技术原理而实现的这些功能,既可以方便我们的生活,也可以学习。
(完)
本文内容所提及均为本地测试或经过目标授权同意,旨在提供教育和研究信息,内容已去除关键敏感信息和代码,以防止被恶意利用。文章内提及的漏洞均已修复,作者不鼓励或支持任何形式的非法行为。