我刚开始学习序列化并尝试实现它。我有一个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;
}
}
答案 0 :(得分:2)
修改强>
我浏览了你的代码,发现你已经先读过这个对象,然后尝试在客户端和服务器上编写它。
客户端和服务器都不应该首先阅读,因为它们都在等待数据。
更改读取和写入的顺序,或者在单独的线程中实现读取和写入。
旧回答:
方法readObject()
应该阻止当前线程,即在收到某些数据之前它不会继续。
解决方案是在客户端的单独后台线程中实现与网络相关的代码。