2013-02-08 81 views
5

我是Java和JavaFX的新手,所以请原谅我的新手问题。过去几天我搜索了我正在尝试做的事情的例子,但一直未能找到任何答案。 下面是我想要做的:我正在尝试使用场景构建器创建一个简单的javafx GUI客户端套接字应用程序,该构建器将连接到服务器并发送/接收数据。很简单,但是当我尝试在Java FX中实现时,我的GUI冻结。我研究并发现,原因是套接字通信一直占用,并且javafx GUI无法更新。我的研究指出我使用任务。因此,我创建了一个创建任务的简单应用程序,连接到互联网套接字(端口80),发送命令“GET/HTTP/1.1 \ r \ n \ r \ n”,它将请求页面,然后打印出每条线都收到。问题是我想一遍又一遍地(每3秒)做一遍。任务成功运行一次,但随后停止。在下面的代码中,线程进入睡眠状态的行永远不会到达,但打印任何错误的行也不会发送到system.out。javafx,套接字编程和线程

这里是控制器代码

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

的Main.java类看起来是这样的:

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

}`

最后的FXML文件看起来像这样:

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

在此先感谢您的帮助 韦恩

+0

你的输出是什么样的?换句话说,服务器第一次回应什么? – 2014-03-26 19:30:54

回答

0

您遇到的问题,与冻结桂是因为它的“控制器”类连接到套接字。当我使用JavaFx和JavaFx场景创建器创建我自己的聊天程序时,我遇到了同样的问题。

你可以做两件事情:

  1. 创建您连接到插座一个新的类(SocketConnector())。

  2. 连接插座上的主类中,而不是controller

无论你不能控制器类中连接到插座我很抱歉,我无法描述的细节,为什么你不能只是知道多次尝试过这个问题,并且这是修复它的方法!

0

有两件事情需要你的要求改变:

  1. 插入到这一点你的要求

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

    这将确保它响应后,服务器不关闭你的连接你的申请。

  2. 更改while循环这样的:

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

    这将确保有东西从BufferedReader中阅读。检查这些帖子关于为什么BufferedReader会挂起:https://stackoverflow.com/a/7855911/1359765https://stackoverflow.com/a/15510821/1359765