2017-10-14 81 views
1

我刚开始学习Serialization并试图实现它。我有一个server,一个client和一个student类。 server创建我的学生课程的初始实例。客户端然后连接到服务器并篡改与学生相关的属性,即颠覆GPA。readObject()挂起程序

由于某种原因,当我尝试client类中的readObject()时,我的代码没有得到结论。无法弄清楚原因。再一次,我对这个话题非常陌生,所以如果我误解了一些关于它的重大或未知的事情,请指出。任何帮助表示赞赏。

这里是我的课:

服务器类:

import java.io.*; 
import java.net.*; 

public class Server 
{ 
    Student s1 = null; 
    ServerSocket sock; 
    ListeningThread thread; 

    public Server(int port) throws IOException { 

     sock = new ServerSocket(port); 

    } // end of constructor 
    // starts the listening thread 
    public void start() { 

     thread = new ListeningThread(); 
     thread.start(); 

    } // end of start method 

    // stops the listening thread 
    public void shutdown() throws IOException { 

     thread.shutdown(); 

    } // end of start method 

    private class ListeningThread extends Thread 
    { 
    Student s1 = new Student(0.5, "ABCDEFG", "Computer Science and Pure Math"); 
    boolean keep_going; 

    public ListeningThread() { 
     super("The thread that listens"); 
    } 

    public void shutdown() throws IOException 
    { 
     keep_going = false; 
     System.out.println("closing server socket"); 
     sock.close(); 

     System.out.println("Waiting for listening thread to exit"); 
     try { join(); } 
     catch(InterruptedException e) {} 

     System.out.println("Server shut down"); 

    } 
    public void run() 
    { 
     // Show student info before connecting to client 
     System.out.println("Student Name is : " + s1.getStudentName()); 
     System.out.println("Student Major is : " + s1.getStudentMajor()); 
     System.out.println("Student GPA is : "+ s1.getStudentGPA()); 
     try 
     { 
      boolean keep_going = true; 
      while(keep_going) 
      { 
      System.out.println("Listening for connection on port "+ 
           sock.getLocalPort()); 
      Socket s = sock.accept(); 

      ClientHandler handler = new ClientHandler(s); 
      handler.start(); 

      System.out.println("Got a connection"); 
      } 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 

    } // end of run method 

    } // end of ListeningThread class 

private class ClientHandler extends Thread 
{ 
     ObjectOutputStream serverOutputStream = null; 
     ObjectInputStream serverInputStream = null; 

     Socket socket; 
    /************************************************************************* 
    * @param socket The Socket object returned by calling accept() on the 
    * ServerSocket. 
    *************************************************************************/ 
    public ClientHandler(Socket socket) throws Exception { 

     this.socket = socket; 

    } // end of constructor 
    public void run() 
    { 
     try 
     { 
     serverInputStream = new ObjectInputStream(socket.getInputStream()); 
     serverOutputStream = new ObjectOutputStream(socket.getOutputStream()); 

     s1 = (Student)serverInputStream.readObject(); 
     System.out.println("DATA HAS BEEN TAMPERED"); 
     serverOutputStream.writeObject(s1); 
     serverOutputStream.flush(); 
      // Show student info after connecting to client, once we tampered with it 
     System.out.println("Student Name is : " + s1.getStudentName()); 
     System.out.println("Student Major is : " + s1.getStudentMajor()); 
     System.out.println("Student GPA is : "+ s1.getStudentGPA()); 

     serverInputStream.close(); 
     }catch(Exception e){e.printStackTrace();} 
    } // end of run method 

    } // end of ClientHandler inner class 
} 

客户端类:

import java.io.*; 
import java.net.*; 

public class Main 
{ 
    public static void main(String[] arg) throws Exception 
    { 
     Student s1 = null; 

     Socket socketConnection = new Socket("127.0.0.1", 9876); 

     ObjectInputStream clientInputStream = new 
     ObjectInputStream(socketConnection.getInputStream()); 

     ObjectOutputStream clientOutputStream = new 
     ObjectOutputStream(socketConnection.getOutputStream()); 

     //System.out.println("I'VE TAMPERED WITH DATA"); 
     //clientOutputStream.writeObject(s1); 

     /***************************************************************** 
      * Funny thing here that stomped me for quite a while is that 
      * .readObject() and .writeObject() exceptions aren't handled by 
      * IOException, which makes sense. And I was trying to catch an 
      * IOException for about 2 hours till I realized that. 
      *****************************************************************/ 

      s1 = (Student)clientInputStream.readObject(); 
      s1.setStudentGPA(4.00); // <<<---- hehe 

      clientOutputStream.writeObject(s1); 
      clientOutputStream.flush(); 

      System.out.println("I'VE TAMPERED WITH DATA 1"); 

     clientInputStream.close(); 
     clientOutputStream.close(); 
     System.out.println("I'VE TAMPERED WITH DATA 1"); 
    } 
} 

和我的学生对象类:

import java.io.*; 
import java.util.*; 

public class Student implements Serializable 
{ 
    private String studentName, studentMajor; 
    private double studentGPA; 

    Student(double gpa, String name, String major) 
    { 
     studentName = name; 
     studentMajor= major; 
     studentGPA = gpa; 
    } 
    //------------------------------------------------------- 
    public String getStudentName() 
    { 
     return studentName ; 
    } 
    public String getStudentMajor() 
    { 
    return studentMajor ; 
    } 
    public double getStudentGPA() 
    { 
    return studentGPA ; 
    } 
    //------------------------------------------------------- 
    public void setStudentGPA(double gpa) 
    { 
    studentGPA = gpa; 
    } 
} 

回答

2

编辑:

我看了你的代码,发现你已经先读对象,并试图在客户端和服务器上写下。

客户端和服务器都不应该先读取,因为它们都会等待数据。

要么改变读取和写入的顺序,要么在不同的线程中实现读取和写入。

旧答案:

方法readObject()应该阻止当前线程,即,它不会继续进行,直到接收到某些数据。

解决方案是在客户端的单独后台线程中实现与网络相关的代码。

+0

你能提供一个伪代码吗?我想我明白,但这会有所帮助。 –

+0

你已经在服务器端实现了Thread,使用类似的方法。 –

+0

好吧,我会尝试。 –