2013-02-08 3 views
5

Sono nuovo in Java e JavaFX, quindi scusate le mie domande per principianti. Ho cercato negli ultimi due giorni esempi di ciò che sto cercando di fare, ma non sono riuscito a trovare alcuna risposta. Ecco cosa sto cercando di fare: sto cercando di creare una semplice applicazione socket client javafx con lo strumento di creazione scene che si connetterà a un server e invierà/riceverà dati. Abbastanza semplice, ma quando provo a implementarlo in Java FX, la mia GUI si blocca. Ho studiato e scoperto che il motivo è che le comunicazioni socket sono sempre in corso e la GUI javafx non può essere aggiornata. La mia ricerca mi ha indicato l'utilizzo dei compiti. Così, ho creato una semplice applicazione che crea un'attività, si connette a un socket internet (porta 80), invia il comando "GET/HTTP/1.1 \ r \ n \ r \ n" che richiederà la pagina e quindi stamperà ogni linea ricevuta. Il problema è che voglio farlo più e più volte (ogni 3 secondi). L'attività viene eseguita correttamente una volta, ma poi si interrompe. Nel seguente codice, le righe che mettono il thread in sleep non vengono mai raggiunte, ma le righe che stampano eventuali errori non vengono inviate a system.out.javafx, programmazione socket e thread

Ecco il codice del controller

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

La classe Main.java assomiglia a questo:

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

} `

E infine il file FXML assomiglia a questo:

<?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> 

Grazie in anticipo per il vostro aiuto Wayne

+0

Che aspetto ha l'output? In altre parole, cosa risponde il server la prima volta? –

risposta

0

Il problema che si ottiene con il Gui che si blocca è perché è la vostra classe "controller" che si collega al socket. Ho avuto lo stesso problema quando stavo creando il mio programma di chat utilizzando JavaFx e JavaFx.

Si possono fare due cose:

  1. creare una nuova classe (SocketConnector()) che si collega alla presa.

  2. Collegare alla presa all'interno della classe principale, invece di controller

a prescindere, non è possibile collegare ad una presa all'interno della vostra classe controller Mi dispiace che io sono in grado di descrivere i dettagli sul motivo per cui non posso semplicemente sappi che ive ha sperimentato questo problema diverse volte e questo è il modo di risolverlo!

0

un paio di cose devono cambiare con la vostra richiesta:

  1. Inserire questo nella vostra richiesta

    "\r\nHost: <host>\r\nConnection: keep-alive" 
    

    Questo farà in modo che il server non chiude la vostra connessione dopo che risponde a la tua richiesta.

  2. Modifica il tuo ciclo while per questo:

    while (s_in.ready() && (response = s_in.readLine()) != null) 
    

    Questo farà in modo che ci sia qualcosa da leggere dal BufferedReader.Controlla questi post sul perché BufferedReader si bloccherà: https://stackoverflow.com/a/7855911/1359765 e https://stackoverflow.com/a/15510821/1359765