有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java从服务器socket获取实时数据并在javafx中显示

您好,我需要从我创建的服务器socket中获取一些数据,并将其显示在javafx应用程序中 fx应用程序ie显示屏每250ms刷新一次数据,服务器每2秒发送一次数据

我的代码/计划主要有三部分
1.服务器生成数据并每2秒将其发送到端口
2.Clint代码从服务器获取数据并更新其全局变量
3.每250毫秒的日程执行者联系clint中的全局变量并更新文本字段
//遗憾的是,这似乎不起作用
我总是先启动服务器,然后clint再运行应用程序

我写的代码如下

服务器代码

import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.DecimalFormat;
import java.util.concurrent.TimeUnit;
public class Server {
    public static void main(String[] args) throws IOException, InterruptedException {
        Socket socket;
        try (ServerSocket serverSocket = new ServerSocket(5555)) {
            System.out.println("A");
            socket = serverSocket.accept();
            System.out.println("B");
            if(socket.isConnected())System.out.println("Connected");
            DataOutputStream dout=new DataOutputStream(socket.getOutputStream());
            while (socket.isConnected()) {
                String T=DataStructureMaker();
                dout.writeUTF(T);
                System.out.println(T);
                TimeUnit.SECONDS.sleep(2);
                dout.flush();
            }
        }
        socket.close();
    } 
    public static String DataStructureMaker()
    {
    float RV_Phase=0,RI_Phase=0,RI_Grid=0,RV_Grid=0;String s="";
        DecimalFormat df = new DecimalFormat("#.00");
        s="";
        RV_Phase=Float.parseFloat(df.format((Math.random()*10)));
        s=s+Float.toString(RV_Phase)+"#";
        RI_Phase=Float.parseFloat(df.format((Math.random()*10)));
        s=s+Float.toString(RI_Phase)+"#";
        RI_Grid=Float.parseFloat(df.format((Math.random()*10)));
        s=s+Float.toString(RI_Grid)+"#";
        RV_Grid=Float.parseFloat(df.format((Math.random()*10)));
        s=s+Float.toString(RV_Grid)+"#";
        return s;
    }
}

克林特密码是

import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
public class Clint {
    public static String RV_Grid;
    public static String RI_Grid;
    public static String RI_Phase;
    public static String RV_Phase;
    public static void main(String[] args) throws IOException, InterruptedException {
        Socket s=new Socket("localhost",5555);
        String S;
        DataInputStream dIn=new DataInputStream(s.getInputStream());
        while (s.isConnected()) {            
            S=dIn.readUTF();
            setData(S);
        }
    }
    public static void setData(String S)  // Decryt data and set global values
    {
        char[] A=S.toCharArray();
        int HC=0;
        String R="";
        if(A.length>2)
        for(char x:A)
        {
            if(x=='#')
            {
                switch(HC)
                {
                    case 0:
                        HC++;
                        RV_Phase=R;
                        R="";
                        break;
                    case 1:
                        HC++;
                        RI_Phase=R;
                        R="";
                        break;
                    case 2:
                        HC++;
                        RI_Grid=R;
                        R="";
                        break;
                    case 3:
                        HC++;
                        RV_Grid=R;
                        R="";
                        break;
                }
            }else{
                R=R+x;
            }
        }
    }    
}

最后是我的fxml控制器

import java.util.ResourceBundle;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextField;
public class FXMLDocumentController implements Initializable {

    @FXML
    private TextField Text1;
    @FXML
    private TextField Text2;
    @FXML
    private TextField Text3;
    @FXML
    private TextField Text4;


    static ScheduledExecutorService scheduledExecutorService;
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO

        scheduledExecutorService =         Executors.newSingleThreadScheduledExecutor();
        scheduledExecutorService.scheduleAtFixedRate(() -> {
            setData();

            }, 0, 250, TimeUnit.MILLISECONDS);
    }    
    public void setData()
    {
        Text1.setText(Clint.RI_Grid);
        Text2.setText(Clint.RI_Phase);
        Text3.setText(Clint.RV_Grid);
        Text4.setText(Clint.RV_Phase);
    }       
}

上面的代码包含了我的程序加密、解密、发送、接收和显示所需的所有重要数据


共 (1) 个答案

  1. # 1 楼答案

    以下代码旨在实现两个目的:
    一个是为所问的问题演示一个mre
    另一个是使用客户端接收的数据动态更新GUI的解决方案
    这段代码的目的不是展示如何正确实现客户机和服务器

    关于MRE,有几点需要注意:
    1.它不应该代表你的具体应用,而应该代表你关注的具体问题 我们正在努力解决这个问题
    2.应该是M:去掉所有不必要的东西。最低限度
    3.应该是R:重现问题
    4.应该是完整的。独立于数据库、文件或其他不可用资源
    5.它应该易于使用(复制过去)

    为了用客户机接收到的数据动态更新GUI,我使用了一个共享模型,该模型由客户机更新
    通过使用绑定在GUI中反映的模型ifs中的任何更改

    为了简单易用,我把控制器、模型、服务器和客户机都放在一个文件中FXMLDocumentController.java

    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.net.URL;
    import java.text.DecimalFormat;
    import java.util.ResourceBundle;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    import javafx.beans.property.ReadOnlyStringWrapper;
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.control.Button;
    import javafx.scene.control.TextField;
    
    public class FXMLDocumentController implements Initializable {
    
        private static int PORT_NUMBER = 5555;
        @FXML
        private TextField text1;
        @FXML
        Button stopButton, startButton;
    
        private ScheduledExecutorService scheduledExecutorService;
        private Model model;
        private Client client;
        private Server server;
    
        @Override
        public void initialize(URL url, ResourceBundle rb) {
            startButton.setDisable(false);
            stopButton.setDisable(true);
            scheduledExecutorService = Executors.newScheduledThreadPool(2);
            model = new Model();
            text1.textProperty().bind(model.getTextProperty());
        }
    
        private void startServer(){
    
            try {
                server = new Server(PORT_NUMBER);
                server.start();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    
        private void startClient(){
    
            try {
                client = new Client(PORT_NUMBER, model);
                client.start();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    
        public void start(){
    
            scheduledExecutorService.submit(() -> startServer());
            scheduledExecutorService.submit(() -> startClient());
    
            startButton.setDisable(true);
            stopButton.setDisable(false);
        }
    
        public void stop(){
    
            client.stop();
            server.stop();
    
            scheduledExecutorService.shutdown();
            stopButton.setDisable(true);
        }
    }
    
    class Model {
    
        private final ReadOnlyStringWrapper textProperty;
    
        Model() {
            textProperty = new ReadOnlyStringWrapper();
        }
    
        synchronized void setText(String s){
            Platform.runLater(()->textProperty.set(s));
        }
    
        ReadOnlyStringWrapper getTextProperty(){
            return textProperty;
        }
    }
    
    class Server {
    
        private final int portNumber;
        private volatile boolean stop = false;
        private static long REFRESH_TIME = 2;
    
        Server(int portNumber) {
            this.portNumber = portNumber;
        }
    
        void start() throws IOException {
    
            Socket socket;
            try (ServerSocket serverSocket = new ServerSocket(portNumber)) {
                socket = serverSocket.accept();
                DataOutputStream dout=new DataOutputStream(socket.getOutputStream());
                while (socket.isConnected() && ! stop) {
                    dout.writeUTF(randomText());
                    try {
                        TimeUnit.SECONDS.sleep(REFRESH_TIME);
                    } catch (InterruptedException ex) {
                        break;
                    }
                    dout.flush();
                }
            }
        }
    
        private String randomText()
        {
            DecimalFormat df = new DecimalFormat("#.00");
            StringBuilder sb = new StringBuilder(df.format(Math.random()*10));
            sb.append("#")
            .append(df.format(Math.random()*10)) ;
            return sb.toString();
        }
    
        void stop(){
            stop = true;
        }
    }
    
    class Client {
    
        private final int portNumber;
        private final Model model;
        private volatile boolean stop = false;
    
        Client(int portNumber,  Model model) {
            this.portNumber = portNumber;
            this.model = model;
        }
    
        void start() throws IOException {
            Socket socket = new Socket("localhost",portNumber);
            DataInputStream dIn=new DataInputStream(socket.getInputStream());
            while (socket.isConnected() && ! stop) {
                model.setText(dIn.readUTF());
            }
            socket.close();
        }
    
        void stop(){
            stop = true;
        }
    }
    

    该控制器由FXMLDocument使用。fxml:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.control.Button?>
    <?import javafx.scene.control.TextField?>
    <?import javafx.scene.layout.GridPane?>
    <?import javafx.scene.layout.VBox?>
    
    <VBox alignment="CENTER" prefHeight="113.0" prefWidth="232.0" spacing="10" xmlns="http://javafx.com/javafx/10.0.1" 
    xmlns:fx="http://javafx.com/fxml/1" fx:controller="fx_tests.FXMLDocumentController">
    
         <TextField fx:id="text1" alignment="CENTER" promptText="Press START " />
         <GridPane>
             <Button fx:id="startButton" maxWidth="Infinity" onAction="#start" text="START" GridPane.columnIndex="0" />
             <Button fx:id="stopButton" maxWidth="Infinity" onAction="#stop" text="STOP" GridPane.columnIndex="2" />
         </GridPane>
    </VBox>
    

    用以下方法进行测试:

    import java.io.IOException;
    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Scene;
    import javafx.scene.layout.Pane;
    import javafx.stage.Stage;
    
    public class FxmlTest extends Application {
    
        @Override
        public void start(Stage primaryStage) throws IOException {
    
            Pane root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
            Scene scene = new Scene(root);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(null);
        }
    }