readObject()挂起程序

时间:2017-10-14 10:23:58

标签: java serialization

我刚开始学习序列化并尝试实现它。我有一个server,一个client和一个student类。 server创建了我的学生班级的初始实例。然后客户端连接到服务器并篡改与学生相关的属性,即加剧GPA。

出于某种原因,当我在readObject()课程中尝试client时,我的代码无法说明问题。无法弄清楚原因。同样,我对这个话题非常陌生,所以如果我误解了一些重大或轻微的问题,请指出。任何帮助表示赞赏。

以下是我的课程:

服务器类:

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

1 个答案:

答案 0 :(得分:2)

修改

我浏览了你的代码,发现你已经先读过这个对象,然后尝试在客户端和服务器上编写它。

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

更改读取和写入的顺序,或者在单独的线程中实现读取和写入。

旧回答:

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

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