JAVA - 使用套接字和线程接收对象不起作用
JAVA - receiving objects using sockets and threads not working
我正在尝试从服务器获取一个对象,但它不起作用。
来自服务器的相关部分(通过调试我看到他确实发送了正确的对象):
public static void main(String[] args){
launch(args);
}
public void start(Stage primaryStage) {
BorderPane mainPane = new BorderPane();
mainPane.setStyle("-fx-border-color: black;");
mainPane.setPadding(new Insets(5,5,5,5));
GridPane gridPane = new GridPane();
gridPane.setPadding(new Insets(5,5,5,5));
gridPane.add(lblStatus,0,1);
gridPane.add(lblDate,0,2);
mainPane.setTop(gridPane);
createTableView();
mainPane.setCenter(tableView);
Scene scene = new Scene(mainPane, 700, 250);
primaryStage.setTitle("Server"); // Set the window title
primaryStage.setScene(scene); // Place the scene in the window
primaryStage.show(); // Display the window
primaryStage.setAlwaysOnTop(true);
primaryStage.setOnCloseRequest(
new EventHandler<WindowEvent>(){
public void handle(WindowEvent event) {
try {
Platform.exit();
System.exit(0);
serverSocket.close();
socket.close();
}
catch(SocketException ex){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
catch (IOException e) {
// TODO Auto-generated catch block
Platform.exit();
System.exit(0);
}
}
});
connectToDB();
connectionDate=new Date();
Platform.runLater(() ->lblDate.setText(("Server started at \t"+connectionDate)));
Platform.runLater(() ->lblStatus.setText(connectionStatus));
new Thread( () ->
{
try{
// Create a server socket
serverSocket = new ServerSocket(8000);
while (true){
// Listen for a connection request
socket = serverSocket.accept();
this.clientNo++;
clientRequest clientDetails = new clientRequest(clientNo, new Date(), "New Clinet");
addRowToServerTable(clientDetails);
new Thread(new HandleAClient(socket)).start();
}
}
catch(SocketException ex){
}
catch(IOException ex){
}
}).start();
}
/** Connect to DB */
private void connectToDB(){
// Connection to the database
try{
Class.forName(driver); // Load the JDBC driver
System.out.println("Driver Loaded");
connection = DriverManager.getConnection(url, username, password); // Establish a connection
System.out.println("Connected to " + url);
connectionStatus = "Connected to \t" + url;
}
catch (java.lang.Exception ex){
ex.printStackTrace();
connectionStatus = ex.toString();
}
}
// Define the thread class for handling new connection
class HandleAClient implements Runnable{
private Socket socket; // A connected socket
/** Construct a thread */
public HandleAClient(Socket socket){
this.socket = socket;
}
/** Run a thread */
public void run(){
try{
// Create data input and output streams
ObjectOutputStream outputToClient = new ObjectOutputStream(
socket.getOutputStream());
DataInputStream inputFromClient = new DataInputStream(
socket.getInputStream());
// Continuously serve the client
while (true){
// Receive sql from the client
String sql = inputFromClient.readUTF();
clientRequest clientDetails = new clientRequest(clientNo, new Date(),"New Query");
addRowToServerTable(clientDetails);
// Execute SQL
Object[] rows = executeSQL(sql);
outputToClient.writeObject(rows);
}
}
catch(SocketException ex){
try{
serverSocket.close();
//socket.close();
}
catch (IOException e){
}
}
catch(IOException ex){
}
}
来自客户端的相关部分(可能是客户端的错误,当它接收到对象时他跳转到线程的“.start();”行):
private void connectToServer(){
try{
// Create a socket to connect to the server
socket = new Socket(host, 8000);
// Create an input stream to receive Object from the server
fromServer = new ObjectInputStream(socket.getInputStream());
// Create an output stream to send data to the server
toServer = new DataOutputStream(socket.getOutputStream());
}
catch (Exception ex){
ex.printStackTrace();
}
}
private void sendAndGetFromServer(String sqlQuery){
new Thread(() ->{
try{
System.out.println("a1");
// Send sql query to server
toServer.writeUTF(sqlQuery);
//toServer.flush();
// Get notification from the server
Student[] rows = (Student[])fromServer.readObject();
setRowsInTable(rows);
}
catch(SocketException ex){
try{
socket.close();
}
catch (IOException e){
}
}
catch (Exception ex){
}
}).start();
我试图根据我在此处阅读的答案分成两个线程(服务器和客户端中的一个输入和另一个输出)---但它没有帮助。
还尝试更改输入和输出的顺序 --- 没有成功。
- 没有错误!
- 客户端未获取对象。
这里有什么问题?
编辑。学生class:
public class Student implements Externalizable
{
private final SimpleIntegerProperty ID;
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
private final SimpleStringProperty address;
private final SimpleObjectProperty<Date> birthDate;
private final SimpleStringProperty department;
private final SimpleIntegerProperty pointsAmount;
private final SimpleObjectProperty<Date> startStudyingDate;
private final SimpleIntegerProperty failedAmount;
private final SimpleDoubleProperty average;
private final SimpleIntegerProperty lavelByGrade;
private final SimpleStringProperty pic;
public Student(int ID, String firstName, String lastName, String address,
Date birthDate, String department,
int pointsAmount, Date startStudyingDate, int failedAmount,
double average, int lavelByGrade, String pic){
this.ID= new SimpleIntegerProperty(ID);
this.firstName= new SimpleStringProperty(firstName);
this.lastName= new SimpleStringProperty(lastName);
this.address= new SimpleStringProperty(address);
this.birthDate= new SimpleObjectProperty<Date>(birthDate);
this.department= new SimpleStringProperty(department);
this.pointsAmount= new SimpleIntegerProperty(pointsAmount);
this.startStudyingDate= new SimpleObjectProperty<Date>(startStudyingDate);
this.failedAmount= new SimpleIntegerProperty(failedAmount);
this.average= new SimpleDoubleProperty(average);
this.lavelByGrade= new SimpleIntegerProperty(lavelByGrade);
this.pic = new SimpleStringProperty(pic);
}
public int getID() {
return ID.get();
}
public void setID(int ID) {
this.ID.set(ID);
}
public String getFirstName() {
return firstName.get();
}
public void setFirstName(String firstName) {
this.firstName.set(firstName);
}
public String getLastName() {
return lastName.get();
}
public void setLastName(String lastName) {
this.lastName.set(lastName);
}
public String getAddress() {
return address.get();
}
public void setAddress(String address) {
this.address.set(address);
}
public Date getBirthDate() {
return birthDate.get();
}
public void setBirthDate(Date birthDate) {
this.birthDate.set(birthDate);
}
public String getDepartment() {
return department.get();
}
public void setDepartment(String department) {
this.department.set(department);
}
public int getPointsAmount() {
return pointsAmount.get();
}
public void setPointsAmount(int pointsAmount) {
this.pointsAmount.set(pointsAmount);
}
public Date getStartStudyingDate() {
return startStudyingDate.get();
}
public void setStartStudyingDate(Date startStudyingDate) {
this.startStudyingDate.set(startStudyingDate);
}
public int getFailedAmount() {
return failedAmount.get();
}
public void setFailedAmount(int failedAmount) {
this.failedAmount.set(failedAmount);
}
public double getAverage() {
return average.get();
}
public void setAverage(Double average) {
this.average.set(average);
}
public int getLavelByGrade() {
return lavelByGrade.get();
}
public void setLavelByGrade(int lavelByGrade) {
this.lavelByGrade.set(lavelByGrade);
}
public String getPic() {
return pic.get();
}
public void setPic(String pic) {
this.pic.set(pic);
}
@Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
setID(in.readInt());
setFirstName((String)in.readObject());
setLastName((String)in.readObject());
setAddress((String)in.readObject());
setBirthDate((Date)in.readObject());
setDepartment((String)in.readObject());
setPointsAmount(in.readInt());
setStartStudyingDate((Date)in.readObject());
setFailedAmount(in.readInt());
setAverage(in.readDouble());
setLavelByGrade(in.readInt());
setPic((String)in.readObject());
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt(getID());
out.writeObject(getFirstName());
out.writeObject(getLastName());
out.writeObject(getAddress());
out.writeObject(getBirthDate());
out.writeObject(getDepartment());
out.writeInt(getPointsAmount());
out.writeObject(getStartStudyingDate());
out.writeInt(getFailedAmount());
out.writeDouble(getAverage());
out.writeInt(getLavelByGrade());
out.writeObject(getPic());
}
}
尝试使用此 post,使用以下文本和可外部化的搜索部分:很长一段时间以来,我认为缺乏对 JavaFX 属性序列化的支持确实阻止了它们在任何服务器端使用容量。
http://www.marshall.edu/genomicjava/2014/05/09/one-bean-to-bind-them-all/
JavaFX 属性不可序列化。因此,如果您尝试序列化一个使用 JavaFX 属性作为其状态的对象,您将得到一个异常。
这里有几个选项。一种是不使用 Java 对象序列化,而是使用其他一些序列化技术,例如用 JSON.
表示对象
另一种选择是实施 Externalizable
而不是 Serializable
。 Externalizable
是 Serializable
的子接口,您可以在其中定义自己的数据序列化和反序列化过程。特别是,不是序列化 JavaFX 属性本身,而是序列化它们的内容。
一个简单的例子:
import java.io.Externalizable ;
import java.io.IOException ;
import java.io.ObjectInput ;
import java.io.ObjectOutput ;
import javafx.beans.property.IntegerProperty ;
import javafx.beans.property.SimpleIntegerProperty ;
import javafx.beans.property.SimpleStringProperty ;
import javafx.beans.property.StringProperty ;
public class Person implements Externalizable {
private final StringProperty name = new SimpleStringProperty();
private final IntegerProperty id = new SimpleIntegerProperty();
public StringProperty nameProperty() {
return name ;
}
public final String getName() {
return nameProperty().get();
}
public final void setName(String name) {
nameProperty().set(name);
}
public IntegerProperty idProperty() {
return id ;
}
public final int getId() {
return idProperty().get();
}
public final void setId(int id) {
idProperty().set(id);
}
// important: must have a no-arg constructor:
public Person() { }
public Person(int id, String name) {
setId(id);
setName(name);
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
// write id then name
// note we write the contents of the properties, not the properties
// themselves, as the properties are not serializable:
out.writeInt(getId());
out.writeObject(getName());
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
// read data back in same order:
setId(in.readInt());
setName((String)in.readObject());
}
}
请注意,此 class 具有非常简单的结构,因此很容易实现这两个方法。对于更复杂的对象——尤其是那些可能具有循环引用的对象——你需要更加努力地工作。
由于上面定义的class实现了Externalizable
,它也实现了Serializable
,可以按照通常的方式序列化:
ObjectOutputStream oos = ... ;
oos.writeObject(new Person(007, "James Bond"));
阅读我在 JavaFX beans and JPA 上的博客 post 了解更多信息。
我正在尝试从服务器获取一个对象,但它不起作用。
来自服务器的相关部分(通过调试我看到他确实发送了正确的对象):
public static void main(String[] args){
launch(args);
}
public void start(Stage primaryStage) {
BorderPane mainPane = new BorderPane();
mainPane.setStyle("-fx-border-color: black;");
mainPane.setPadding(new Insets(5,5,5,5));
GridPane gridPane = new GridPane();
gridPane.setPadding(new Insets(5,5,5,5));
gridPane.add(lblStatus,0,1);
gridPane.add(lblDate,0,2);
mainPane.setTop(gridPane);
createTableView();
mainPane.setCenter(tableView);
Scene scene = new Scene(mainPane, 700, 250);
primaryStage.setTitle("Server"); // Set the window title
primaryStage.setScene(scene); // Place the scene in the window
primaryStage.show(); // Display the window
primaryStage.setAlwaysOnTop(true);
primaryStage.setOnCloseRequest(
new EventHandler<WindowEvent>(){
public void handle(WindowEvent event) {
try {
Platform.exit();
System.exit(0);
serverSocket.close();
socket.close();
}
catch(SocketException ex){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
catch (IOException e) {
// TODO Auto-generated catch block
Platform.exit();
System.exit(0);
}
}
});
connectToDB();
connectionDate=new Date();
Platform.runLater(() ->lblDate.setText(("Server started at \t"+connectionDate)));
Platform.runLater(() ->lblStatus.setText(connectionStatus));
new Thread( () ->
{
try{
// Create a server socket
serverSocket = new ServerSocket(8000);
while (true){
// Listen for a connection request
socket = serverSocket.accept();
this.clientNo++;
clientRequest clientDetails = new clientRequest(clientNo, new Date(), "New Clinet");
addRowToServerTable(clientDetails);
new Thread(new HandleAClient(socket)).start();
}
}
catch(SocketException ex){
}
catch(IOException ex){
}
}).start();
}
/** Connect to DB */
private void connectToDB(){
// Connection to the database
try{
Class.forName(driver); // Load the JDBC driver
System.out.println("Driver Loaded");
connection = DriverManager.getConnection(url, username, password); // Establish a connection
System.out.println("Connected to " + url);
connectionStatus = "Connected to \t" + url;
}
catch (java.lang.Exception ex){
ex.printStackTrace();
connectionStatus = ex.toString();
}
}
// Define the thread class for handling new connection
class HandleAClient implements Runnable{
private Socket socket; // A connected socket
/** Construct a thread */
public HandleAClient(Socket socket){
this.socket = socket;
}
/** Run a thread */
public void run(){
try{
// Create data input and output streams
ObjectOutputStream outputToClient = new ObjectOutputStream(
socket.getOutputStream());
DataInputStream inputFromClient = new DataInputStream(
socket.getInputStream());
// Continuously serve the client
while (true){
// Receive sql from the client
String sql = inputFromClient.readUTF();
clientRequest clientDetails = new clientRequest(clientNo, new Date(),"New Query");
addRowToServerTable(clientDetails);
// Execute SQL
Object[] rows = executeSQL(sql);
outputToClient.writeObject(rows);
}
}
catch(SocketException ex){
try{
serverSocket.close();
//socket.close();
}
catch (IOException e){
}
}
catch(IOException ex){
}
}
来自客户端的相关部分(可能是客户端的错误,当它接收到对象时他跳转到线程的“.start();”行):
private void connectToServer(){
try{
// Create a socket to connect to the server
socket = new Socket(host, 8000);
// Create an input stream to receive Object from the server
fromServer = new ObjectInputStream(socket.getInputStream());
// Create an output stream to send data to the server
toServer = new DataOutputStream(socket.getOutputStream());
}
catch (Exception ex){
ex.printStackTrace();
}
}
private void sendAndGetFromServer(String sqlQuery){
new Thread(() ->{
try{
System.out.println("a1");
// Send sql query to server
toServer.writeUTF(sqlQuery);
//toServer.flush();
// Get notification from the server
Student[] rows = (Student[])fromServer.readObject();
setRowsInTable(rows);
}
catch(SocketException ex){
try{
socket.close();
}
catch (IOException e){
}
}
catch (Exception ex){
}
}).start();
我试图根据我在此处阅读的答案分成两个线程(服务器和客户端中的一个输入和另一个输出)---但它没有帮助。 还尝试更改输入和输出的顺序 --- 没有成功。
- 没有错误!
- 客户端未获取对象。
这里有什么问题?
编辑。学生class:
public class Student implements Externalizable
{
private final SimpleIntegerProperty ID;
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
private final SimpleStringProperty address;
private final SimpleObjectProperty<Date> birthDate;
private final SimpleStringProperty department;
private final SimpleIntegerProperty pointsAmount;
private final SimpleObjectProperty<Date> startStudyingDate;
private final SimpleIntegerProperty failedAmount;
private final SimpleDoubleProperty average;
private final SimpleIntegerProperty lavelByGrade;
private final SimpleStringProperty pic;
public Student(int ID, String firstName, String lastName, String address,
Date birthDate, String department,
int pointsAmount, Date startStudyingDate, int failedAmount,
double average, int lavelByGrade, String pic){
this.ID= new SimpleIntegerProperty(ID);
this.firstName= new SimpleStringProperty(firstName);
this.lastName= new SimpleStringProperty(lastName);
this.address= new SimpleStringProperty(address);
this.birthDate= new SimpleObjectProperty<Date>(birthDate);
this.department= new SimpleStringProperty(department);
this.pointsAmount= new SimpleIntegerProperty(pointsAmount);
this.startStudyingDate= new SimpleObjectProperty<Date>(startStudyingDate);
this.failedAmount= new SimpleIntegerProperty(failedAmount);
this.average= new SimpleDoubleProperty(average);
this.lavelByGrade= new SimpleIntegerProperty(lavelByGrade);
this.pic = new SimpleStringProperty(pic);
}
public int getID() {
return ID.get();
}
public void setID(int ID) {
this.ID.set(ID);
}
public String getFirstName() {
return firstName.get();
}
public void setFirstName(String firstName) {
this.firstName.set(firstName);
}
public String getLastName() {
return lastName.get();
}
public void setLastName(String lastName) {
this.lastName.set(lastName);
}
public String getAddress() {
return address.get();
}
public void setAddress(String address) {
this.address.set(address);
}
public Date getBirthDate() {
return birthDate.get();
}
public void setBirthDate(Date birthDate) {
this.birthDate.set(birthDate);
}
public String getDepartment() {
return department.get();
}
public void setDepartment(String department) {
this.department.set(department);
}
public int getPointsAmount() {
return pointsAmount.get();
}
public void setPointsAmount(int pointsAmount) {
this.pointsAmount.set(pointsAmount);
}
public Date getStartStudyingDate() {
return startStudyingDate.get();
}
public void setStartStudyingDate(Date startStudyingDate) {
this.startStudyingDate.set(startStudyingDate);
}
public int getFailedAmount() {
return failedAmount.get();
}
public void setFailedAmount(int failedAmount) {
this.failedAmount.set(failedAmount);
}
public double getAverage() {
return average.get();
}
public void setAverage(Double average) {
this.average.set(average);
}
public int getLavelByGrade() {
return lavelByGrade.get();
}
public void setLavelByGrade(int lavelByGrade) {
this.lavelByGrade.set(lavelByGrade);
}
public String getPic() {
return pic.get();
}
public void setPic(String pic) {
this.pic.set(pic);
}
@Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
setID(in.readInt());
setFirstName((String)in.readObject());
setLastName((String)in.readObject());
setAddress((String)in.readObject());
setBirthDate((Date)in.readObject());
setDepartment((String)in.readObject());
setPointsAmount(in.readInt());
setStartStudyingDate((Date)in.readObject());
setFailedAmount(in.readInt());
setAverage(in.readDouble());
setLavelByGrade(in.readInt());
setPic((String)in.readObject());
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt(getID());
out.writeObject(getFirstName());
out.writeObject(getLastName());
out.writeObject(getAddress());
out.writeObject(getBirthDate());
out.writeObject(getDepartment());
out.writeInt(getPointsAmount());
out.writeObject(getStartStudyingDate());
out.writeInt(getFailedAmount());
out.writeDouble(getAverage());
out.writeInt(getLavelByGrade());
out.writeObject(getPic());
}
}
尝试使用此 post,使用以下文本和可外部化的搜索部分:很长一段时间以来,我认为缺乏对 JavaFX 属性序列化的支持确实阻止了它们在任何服务器端使用容量。
http://www.marshall.edu/genomicjava/2014/05/09/one-bean-to-bind-them-all/
JavaFX 属性不可序列化。因此,如果您尝试序列化一个使用 JavaFX 属性作为其状态的对象,您将得到一个异常。
这里有几个选项。一种是不使用 Java 对象序列化,而是使用其他一些序列化技术,例如用 JSON.
表示对象另一种选择是实施 Externalizable
而不是 Serializable
。 Externalizable
是 Serializable
的子接口,您可以在其中定义自己的数据序列化和反序列化过程。特别是,不是序列化 JavaFX 属性本身,而是序列化它们的内容。
一个简单的例子:
import java.io.Externalizable ;
import java.io.IOException ;
import java.io.ObjectInput ;
import java.io.ObjectOutput ;
import javafx.beans.property.IntegerProperty ;
import javafx.beans.property.SimpleIntegerProperty ;
import javafx.beans.property.SimpleStringProperty ;
import javafx.beans.property.StringProperty ;
public class Person implements Externalizable {
private final StringProperty name = new SimpleStringProperty();
private final IntegerProperty id = new SimpleIntegerProperty();
public StringProperty nameProperty() {
return name ;
}
public final String getName() {
return nameProperty().get();
}
public final void setName(String name) {
nameProperty().set(name);
}
public IntegerProperty idProperty() {
return id ;
}
public final int getId() {
return idProperty().get();
}
public final void setId(int id) {
idProperty().set(id);
}
// important: must have a no-arg constructor:
public Person() { }
public Person(int id, String name) {
setId(id);
setName(name);
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
// write id then name
// note we write the contents of the properties, not the properties
// themselves, as the properties are not serializable:
out.writeInt(getId());
out.writeObject(getName());
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
// read data back in same order:
setId(in.readInt());
setName((String)in.readObject());
}
}
请注意,此 class 具有非常简单的结构,因此很容易实现这两个方法。对于更复杂的对象——尤其是那些可能具有循环引用的对象——你需要更加努力地工作。
由于上面定义的class实现了Externalizable
,它也实现了Serializable
,可以按照通常的方式序列化:
ObjectOutputStream oos = ... ;
oos.writeObject(new Person(007, "James Bond"));
阅读我在 JavaFX beans and JPA 上的博客 post 了解更多信息。