Javafx, socket programming and threads

I am new to Java and JavaFX, so I apologize for my newbies. I searched the past couple of days for examples of what I'm trying to do, but could not find the answers. Here is what I am trying to do: I am trying to create a simple javafx GUI client socket application using a scene builder that will connect to the server and send / receive data. Simple enough, but when I try to implement this in Java FX, my GUI freezes. I researched and found out that the reason is that socket communication takes all the time, and the javafx GUI cannot be updated. In my research, I pointed out the use of tasks. So, I created a simple application that creates a task, connects to an Internet socket (port 80), sends the command "GET / HTTP / 1.1 \ r \ n \ r \ n", which requests a page,and then prints out each line received. The problem is that I want to do it again and again (every 3 seconds). The task succeeds once, but then it stops. In the following code, the lines in which the thread slept are never reached, but the lines that print any errors are not sent to system.out.

Here is the controller code

package clientSocketExample;

import java.io.*;
import java.net.*;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.concurrent.Task;

/**
 * Controller class of the HelloWorld sample.
 */
public class ClientSocketExampleController implements Initializable
{

    @FXML
    Button button;

    private boolean keepRunning = true;

    /**
     * Initializes the controller class.
     */
    @Override
    public void initialize(URL url, ResourceBundle rsrcs)
    {
            if (button != null)
        {
            button.setOnAction(new EventHandler<ActionEvent>()
            {
                @Override
                public void handle(ActionEvent event)
                {
                    keepRunning = false;
                    System.out.println("Hello World\n");
                }
            });
        }

        // Create a background task to handle the Client-Server socket
        // This is needed because JavaFX is not thread safe
        Task<Integer> task = new Task<Integer>()
        {
             @Override
            protected Integer call() throws Exception
            {
                Socket s = new Socket();
//                String host = "www.google.com";
//                String host = "www.amazon.com";
                String host = "www.yahoo.com";
                PrintWriter s_out = null;
                BufferedReader s_in = null;
                int lineNums = 0;

                try
                {
                    s.connect(new InetSocketAddress(host, 80));
                    System.out.println("Connected\n");

                    // Create writer for socket
                    s_out = new PrintWriter(s.getOutputStream(), true);

                    // Create reader for socket
                    s_in = new BufferedReader(new     InputStreamReader(s.getInputStream()));
                }
                catch (IOException e)
                {
                    // Host not found, so print error
                    System.err.println("Don't know about host : " + host);
                    System.exit(1);
                }

                // Loop forever waiting for task to be cancelled
                while (isCancelled() == false)
                {
                    // Send message to server
                    String message = "GET / HTTP/1.1\r\n\r\n";
                    s_out.println(message);

                    System.out.println("Message sent\n");
                    // Get response from server
                    try
                    {
                        String response;
                        while ((response = s_in.readLine()) != null)
                        {
                            System.out.print("Line #: "+lineNums+" ");
                            System.out.println(response);
                            lineNums++;
                        }
                    } catch (IOException e)
                    {
                        System.err.println("Couldn't get response from host");
                    }

                    System.out.println("Thread going to sleep\n\n\n");
                    Thread.sleep(3000);
                    System.out.println("Thread waking up from sleep\n\n\n");
                } // End while

                return lineNums;
            }           
        }; // End Initialize

        // start the background task
        Thread th = new Thread(task);
        th.setDaemon(true);
        System.out.println("Starting background task...");
        th.start();
    }
}`

The Main.java class is as follows:

package clientSocketExample;

import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

public class Main extends Application
{
/**
 * @param args the command line arguments
 */
public static void main(String[] args)
{
    Application.launch(Main.class, (java.lang.String[]) null);
}

@Override
public void start(Stage primaryStage)
{
    try
    {
        AnchorPane page = (AnchorPane) FXMLLoader.load(Main.class
                .getResource("ClientSocketExample.fxml"));
        Scene scene = new Scene(page);
        primaryStage.setScene(scene);
        primaryStage.setTitle("Hello World Sample");
        primaryStage.show();
    } catch (Exception ex)
    {
        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    }
}

} `

And finally, the FXML file looks like this:

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>

<AnchorPane id="AnchorPane" prefHeight="365.0" prefWidth="378.0"     xmlns:fx="http://javafx.com/fxml"     fx:controller="clientSocketExample.ClientSocketExampleController">
  <children>
    <Button fx:id="button" layoutX="147.0" layoutY="28.0" text="Connect" />
    <TitledPane animated="false" layoutY="159.0" prefWidth="378.0" text="Received Data">
      <content>
        <AnchorPane id="Content" minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
          <children>
            <TextArea fx:id="textAreaField" prefHeight="180.0" prefWidth="374.0" wrapText="true" />
          </children>
        </AnchorPane>
      </content>
    </TitledPane>
  </children>
</AnchorPane>

Thanks in advance for helping Wayne

+5
source share
2 answers

The problem you are facing with Gui freezing is that its class is a “controller” that connects to the socket. I had the same problem when I created my own chat program using the JavaFx and JavaFx scene.

You can do two things:

  • Create a new class ( SocketConnector()) that connects you to the socket.

  • Connect to a socket in the main class instead controller

, , , , , ive , , !

0

:

0

All Articles