JAVA - 使用套接字和线程接收对象不工作 [英] JAVA - receiving objects using sockets and threads not working

查看:256
本文介绍了JAVA - 使用套接字和线程接收对象不工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图从服务器获取一个对象,但它不工作。

I'm trying to get an object from the server, but it does not work.

服务器的相关部分(通过Debug我看到他真的发送正确的对象):

Relevant section from the server (By Debug I see that he is really sending the correct object):

    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 ;Of the Thread。):

Relevant section from the client (Probably the mistake on the client, when it receives the object he jumps line ".start ();" Of the Thread.):

    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();

我试图分成两个线程(一个输入和其他输出在服务器和客户端)根据答案我读这里---但它没有帮助。
也尝试更改输入和输出顺序---未成功。

I tried to separate into two Thread (One Input and other Output in Server and client) according to the answers I read here --- but it didn't help. Also tried to change the order of Input and Output --- without success.


  • 没有错误!

  • 客户没有获得对象。

这里有什么问题?

编辑。学生类:

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()); 

    }
}   


推荐答案

JavaFX属性不可序列化。因此,如果你尝试序列化一个使用JavaFX属性的对象的状态,你会得到一个异常。

JavaFX properties are not Serializable. So if you try to serialize an object that uses JavaFX properties for its state, you will get an exception.

这里有几个选项。一个是简单地不使用Java对象序列化,而是一些其他的序列化技术,例如用JSON表示对象。

You have a couple of options here. One is simply to not use Java object serialization, but some other serialization technique, such as representing the object with JSON.

另一个选项是实现 Externalizable 而不是 Serializable 可外化 Serializable 的子接口,您可以在其中定义自己的用于序列化和反序列化数据的过程。特别是,不是序列化JavaFX属性本身,而是序列化它们的内容。

The other option is to implement Externalizable instead of Serializable. Externalizable is a subinterface of Serializable in which you define your own process for serializing and deserializing the data. In particular, instead of serializing the JavaFX properties themselves, just serialize their contents.

一个简单的例子:

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

注意,这个类有一个非常简单的结构,它很容易实现这两种方法。

Note that this class has a pretty simple structure, so it's easy to implement these two methods. For more complex objects - particularly those which may potentially have circular references - you need to work a bit harder.

由于上面定义的类实现了 Externalizable(),因此对于更复杂的对象(特别是那些可能有循环引用的对象) ,它还实现了 Serializable ,并且可以以通常的方式序列化:

Since the class defined above implements Externalizable, it also implements Serializable, and can be serialized in the usual way:

ObjectOutputStream oos = ... ;
oos.writeObject(new Person(007, "James Bond"));

阅读我的博客文章 JavaFX bean和JPA

这篇关于JAVA - 使用套接字和线程接收对象不工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆