javafx,套接字编程和线程 [英] javafx, socket programming, and threads
问题描述
我是Java和JavaFX的新手,所以请原谅我的新手问题。我过去几天搜索了我想要做的事情的例子,但一直找不到任何答案。
以下是我要做的事情:我正在尝试使用将连接到服务器并发送/接收数据的场景构建器创建一个简单的javafx GUI客户端套接字应用程序。很简单,但是当我尝试在Java FX中实现它时,我的GUI冻结了。我研究并发现原因是套接字通信一直在占用,而javafx GUI无法更新。我的研究指出我使用任务。所以,我创建了一个创建任务的简单应用程序,连接到互联网套接字(端口80),发送命令GET / HTTP / 1.1 \\\\\\\ n,它将请求页面然后打印出收到的每一行。问题是我想一遍又一遍地做这件事(每3秒钟)。任务成功运行一次,但随后停止。在下面的代码中,永远不会到达使线程处于休眠状态的行,但是打印任何错误的行也不会发送到system.out。
I am new to Java and JavaFX, so pardon my newbie questions. I have searched for the past couple of days for examples of what I am trying to do, but have been unable to find any answers. Here is what I am trying to do: I am trying to create a simple javafx GUI client socket application using scene builder that will connect to a server and send/receive data. Simple enough, but when I try to implement this in Java FX, my GUI freezes. I have researched and found out that the reason is that the socket communications is taking all of the time, and the javafx GUI cannot update. My research has pointed me to using tasks. So, I have 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 will request the page and then prints out each line received. The problem is that I want to do this over and over again (every 3 seconds). The task runs successfully once, but then it stops. In the following code, the lines that put the thread to sleep are never reached, but the lines that print any errors are not sent to system.out either.
这是控制器代码
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类看起来像这样: / p>
The Main.java class looks like this:
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文件如下所示:
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>
预先感谢您的帮助
Wayne
Thanks in advance for your help Wayne
推荐答案
有些事情需要根据您的要求进行更改:
A couple things need to change with your request:
-
将此插入到您的请求中
Insert this into your request
"\r\nHost: <host>\r\nConnection: keep-alive"
这将确保服务器在响应您的请求后不会关闭您的连接。
This will make sure that the server doesn't close your connection after it responds to your request.
将你的while循环更改为:
Change your while loop to this:
while (s_in.ready() && (response = s_in.readLine()) != null)
这将确保从BufferedReader中读取内容。查看这些帖子,了解BufferedReader将挂起的原因: https://stackoverflow.com/a/7855911/1359765 和 https://stackoverflow.com/a/15510821/1359765
This will make sure there is something to read from the BufferedReader. Check these posts about why the BufferedReader will hang: https://stackoverflow.com/a/7855911/1359765 and https://stackoverflow.com/a/15510821/1359765
这篇关于javafx,套接字编程和线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!