虽然学计算机出身但平时不怎么编程,现在学习Java也不过是初学者的水平。
想要自己编一个小程序来控制电脑,开始用的是C#,后来想同时弄一个Android手机端,索性用Java一起搞。
想要远程控制必须要做网络,所以开始接触Socket。
仅在此处记录一下自己的一些小总结。
(我的需求)想要做一个小程序,需求上不过是一句话:通过远程客户端来控制执行本机的一些程序。
所以最初就规划了两个类 :socketServer 和 localExecutor 一个接收命令,一个执行命令。
下面把代码也贴一下,实现了最简单的几个功能,侦听端口,收消息,写消息和关闭。参考网上,也是弄了好久才弄成。
<span style="font-size:14px;">package ctrl.svr;
import java.net.*;
import java.io.*;
//import java.util.*;
public class SimpleServer {
private int sPORT=2016;
// private String sIP="127.0.0.1";
private ServerSocket ss;
private Socket s;
private DataInputStream din;
private DataOutputStream dout;
// private int timeout=90000;
public String Msg="none";
public SimpleServer(Socket st,int ssport) //构造方法1 如果需要全局的socket的话
{
this.sPORT=ssport;
this.s=st;
try{
ss = new ServerSocket(sPORT);
//ss.setSoTimeout(timeout);
}catch(Exception e)
{
System.out.println("guozao");;
}
}
public SimpleServer(int ssport) //构造方法2
{
this.sPORT=ssport;
try{
ss = new ServerSocket(sPORT);
// ss.setSoTimeout(timeout); //原来还想设置个超时的,但发现没有必要
}catch(Exception e)
{
System.out.println("not creat");;
}
}
public boolean SetUp() //建立 侦听 端口
{
try
{
System.out.println("runing");
s=ss.accept(); //开始 阻塞侦听
Msg=s.getInetAddress().toString()+"@"+s.getPort();
System.out.println(Msg);
din=new DataInputStream(s.getInputStream()); //输入流
return true;
}catch(Exception e)
{
System.out.println(e.getStackTrace()+"/setup");
return false;
}
}
public String ReadMessage()
{
String str=null;
try{
if((str=din.readUTF())!=null) //阻塞读
{return str;}
}catch(Exception e)
{
System.out.println(e.getStackTrace()+"/read");
}
return null;
}
public void WriteMessage(String str)
{
try{
dout=new DataOutputStream(s.getOutputStream());
dout.writeUTF(str);
}catch(Exception e)
{e.printStackTrace();}
}
public boolean shutinput()
{
try{
s.shutdownInput();
din.close(); //跳出读阻塞
return true;
}catch(Exception e)
{
return false;
}
}
public int SClose()
{
try{
ss.close(); //跳出accept阻塞
if(ss.isClosed())
{
ss = new ServerSocket(sPORT); //直接赋值,方便下次继续
System.out.println("socketserver is closed");
}
Msg="none";
return 1;
} catch(Exception e)
{System.out.println("Sever closing error");
}
return 0;
}
}</span>
<span style="font-size:14px;">package ctrl.svr;
import java.io.*;
public class LocalExecutor {
private final String spliter=" ";
private String[] cmd;
//private Runtime rt=Runtime.getRuntime();
private Process p;
public LocalExecutor(String str)
{
this.cmd=str.split(spliter); //以空格为分隔符分割字符串
}
public int StartUp()
{
//cmd[0]="E:\\cpuz_x32.exe";
try {
if(cmd.length<=1)
p=Runtime.getRuntime().exec(cmd[0]);
else p=Runtime.getRuntime().exec(cmd); //执行cmd 并返回process
// return p.waitFor(); //直到子程序结束才返回i
return 1;
}catch(Exception e)
{
System.out.println(e.getStackTrace());
System.out.println("something happened here");
}
return 0;
}
public void ProcessReader()
{
InputStreamReader isr = new InputStreamReader(p.getInputStream());
BufferedReader br = new BufferedReader(isr); //BufferedReader缓冲字符集
String line;
try {
while((line=br.readLine())!=null)
{
System.out.println(line);
}
isr.close();
br.close();
//p.destroy();
}
catch(Exception e) {System.out.println(e.getStackTrace());}
System.out.println("done");
}
public void PClose()
{
p.destroy();
}
}
</span>
然后用swing折腾了一个界面
把Socket连接放在线程里
<span style="font-size:14px;">package ui.svr;
import java.net.Socket;
import ctrl.svr.*;
public class SvrInThread extends ctrl.svr.SimpleServer implements Runnable
{
public SvrInThread(int ssport) {
super(ssport);
// TODO Auto-generated constructor stub
}
public SvrInThread(Socket s,int i){
super(s,i);
}
@Override
public void run() {
// TODO Auto-generated method stub
String c=null;
LocalExecutor ex;
while(this.SetUp())
{
if(Global.flag)
{
Global.labGlobal.setText(this.Msg); \\这个就是那个显示Port:3030的那个label,用于显示收到的消息
c=null;
while((c=this.ReadMessage())!=null)
{
Global.labGlobal.setText(c);
ex=new LocalExecutor(c);
ex.StartUp();
}
Global.labGlobal.setText("Waiting");
if(!Global.flag)
{
this.SClose();
break;
}
}
else{
this.SClose();
break;
}
}
System.out.println("Goodbye");
}
}</span>
因为要重复执行线程所以又弄了一个单线程的线程池。
<span style="font-size:14px;">package ui.svr;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.swing.JButton;
import javax.swing.JLabel;
public class Global {
public static JButton btnGlobal = new JButton("RUN");
public static JLabel labGlobal = new JLabel("Port:3030");
public static boolean flag=false;
public static ExecutorService pool = Executors.newSingleThreadExecutor();
}
</span>
Global就是一个类,放一些全局的变量之类的。
<span style="font-size:14px;">Global.pool.execute(sit);</span>
这样一个单用户的程序执行的服务端就弄完了,很是简陋,反正自己玩玩的。后面的打算用AutoHotKey做一些小程序帮自己更好的控制电脑。
做这么一个小程序也遇到过很多的问题。前面两个主要的功能类倒是问题不大,网上的参考很多。主要问题集中在线程里,找到用线程池这个方法就花了好长的时间。还有一个就是自己作死想要做个关闭连接的开关,和accept()与readUTF() 这两个阻塞玩到头大。不过是调用close()方法跳出阻塞而已。哎~~~~,还以为要强关线程呢,线程的interrupt()非常不给力,stop()又过时了……