我就是试试Java中的Socket

    虽然学计算机出身但平时不怎么编程,现在学习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>

    然后是本地执行程序的类,通过空格分隔命令之后,直接用getRuntime.exec(cmd)就差不多完成了。
<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()又过时了……




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值