我刚刚开始学习序列化并尝试实现它。我有一个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;
}
}
最佳答案
编辑:
我仔细阅读了您的代码,发现您首先阅读了该对象,然后尝试在客户端和服务器中都将其写入。
客户端和服务器都不应首先读取,因为它们都将等待数据。
更改读取和写入的顺序,或在单独的线程中实现读取和写入。
旧答案:
方法readObject()
应该阻塞当前线程,即,直到接收到某些数据后,该方法才会继续进行。
解决方案是在客户端中的单独后台线程中实现与网络相关的代码。
关于java - readObject()挂起程序,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46743427/