介绍
网络编程课上的实验,利用socket写的一个远程控制软件,能够实现对多个客户端基本的shell命令 cd mkdir touch rm(rd) copy,还能实现监控命令传回当前桌面截图,第一次被控制端连接时自动截图传回
;
服务器端:
import com.sun.xml.internal.org.jvnet.mimepull.CleanUpExecutorFactory;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.Buffer;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Scanner;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import static java.lang.Thread.sleep;
public class ServerFrom extends JFrame{
private int num_Image = 0 ;
private JTextArea area;//在线的用户信息显示
private DefaultListModel<String> dataModel; //在线的用户列表显示
private boolean isControl = true ;
private String contorl_name ;
//注册的用户名不能相同
//用于存储所有的用户,这里采用注册的"用户名"做key值,通信的socket做value值
private Map<String, Socket> userMap=new HashMap<String, Socket>();
public ServerFrom() {
setTitle("聊天服务器");
setDefaultCloseOperation(EXIT_ON_CLOSE);
Toolkit toolkit=Toolkit.getDefaultToolkit();
Dimension dim=toolkit.getScreenSize();
int runWidth=500;
int runHeight=400;
int width=(int) dim.getWidth();
int height=(int) dim.getHeight();
//设置界面居中显示
setBounds(width/2-runWidth/2, height/2-runHeight/2, runWidth, runHeight);
area=new JTextArea();
area.setEditable(false);
getContentPane().add(new JScrollPane(area),BorderLayout.CENTER);
//列表显示
dataModel=new DefaultListModel<String>();
JList<String> list=new JList<String>(dataModel);
JScrollPane scroll=new JScrollPane(list);
scroll.setBorder(new TitledBorder("在线"));
scroll.setPreferredSize(new Dimension(100, this.getHeight()));
getContentPane().add(scroll,BorderLayout.WEST);
//菜单
JMenuBar menuBar=new JMenuBar();
setJMenuBar(menuBar);
JMenu menu=new JMenu("控制(C)");
menu.setMnemonic('C'); //设置快捷键为 Alt+C
menuBar.add(menu);
//开启
final JMenuItem itemRun=new JMenuItem("开启");
//快捷键 Ctrl+R
itemRun.setAccelerator(KeyStroke.getKeyStroke('R', KeyEvent.CTRL_MASK));
itemRun.setActionCommand("run");
menu.add(itemRun);
//退出
JMenuItem itemExit=new JMenuItem("退出");
itemExit.setAccelerator(KeyStroke.getKeyStroke('E', KeyEvent.CTRL_MASK));
itemExit.setActionCommand("exit");
menu.add(itemExit);
itemRun.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if("run".equals(e.getActionCommand())){
startServer();
itemRun.setEnabled(false);
}
}
});
setVisible(true);
}
private void startServer() {
try {
System.out.println("服务器启动");
ServerSocket server=new ServerSocket(8090);
area.append("启动服务器:"+server);
//单独开启一个线程用于与客户端握手
new ServerThread(server).start();
new ClientThread_M().start();
} catch (IOException e) {
e.printStackTrace();
}
}
class ServerThread extends Thread{
private ServerSocket server;
public ServerThread(ServerSocket server) {
this.server=server;
}
@Override
public void run() {
try {
while(true) {
if (isControl == true) {
Socket s = server.accept();
Scanner sc = new Scanner(s.getInputStream());
if (sc.hasNext()) {
String userName = sc.next();
contorl_name = userName;
area.append("\r\n" + userName + "控制端上线了。" + s);
dataModel.addElement(userName + " 控制端");
userMap.put(userName, s);
}
new ClientThread(s).start();
isControl = false;
}
else {
Socket s = server.accept();
Scanner sc = new Scanner(s.getInputStream());
InputStream in = s.getInputStream();
if (sc.hasNext()) {
String userName = sc.next();
area.append("\r\n" + userName + "被控制端上线了。" + s);
dataModel.addElement(userName);
sendMsgToCon(userName);
userMap.put(userName, s);
}
// new ClientThread(s).start();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void sendMsgToCon(String userName) throws IOException{
Socket s=userMap.get(contorl_name);
PrintWriter pw=new PrintWriter(s.getOutputStream(),true);
//服务器向客户端发的消息格式设计:
//命令关键字@#发送方@#消息内容
String msg="msg@#server@#"+userName+"登录了"; //用于显示用的.
pw.println(msg);
msg="cmdAdd@#server@#"+userName; //用于给客户端维护在线用户列表用的
pw.println(msg);
// pw.close();
// s.close();
}
class ClientThread_M extends Thread{
public void run() {
while (true)
{
for (Socket s : userMap.values()) {
try {
if (s.getInputStream().available() > 0) {
Scanner sc = new Scanner(s.getInputStream());
while (s.getInputStream().available() > 0) {
String msg = sc.nextLine();
area.append(msg + "\n");
String msgs[] = msg.split("@#");
//简单用户名处理(防黑)。
//命令关键字@#接收方@#消息内容@#发送方
if (msgs == null || msgs.length != 4) {
System.out.println("通讯异常1:" + msg);
return;
}
if ("send".equals(msgs[0])) {//表示客户端的请求是:向别人发送信息
try {
sendMsgToSb(msgs);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else if ("exit".equals(msgs[0])) {//表示客户端发送的请求是:退出(下线)
area.append("\r\n" + msgs[3] + "下线了" + s);
dataModel.removeElement(msgs[3]);
userMap.remove(msgs[3]);
//通知其他所有在线的用户,***退出了
// sendSbExitMsgToAll(msgs);
sendSbExitMsgToCon(msgs);
}
//@#image@#发送者@#文件长度
if ("image".equals(msgs[0])) {
ImageToCon(msg);
}
}
} else {
continue;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
class ClientThread extends Thread{
private Socket con ;
ClientThread(Socket s ){
con = s ;
}
public void run() {
while (true)
{
try {
if (con.getInputStream().available() > 0) {
Scanner sc = new Scanner(con.getInputStream());
while (sc.hasNext())
{
String msg = sc.nextLine() ;
area.append(msg+"\n");
String msgs[] = msg.split("@#");
//简单用户名处理(防黑)。
//命令关键字@#接收方@#消息内容@#发送方
if (msgs == null || msgs.length != 4) {
System.out.println("通讯异常1:" + msg);
return;
}
if ("send".equals(msgs[0])) {//表示客户端的请求是:向别人发送信息
try {
sendMsgToSb(msgs);
} catch (InterruptedException e) {