javafx,套接字编程和线程 [英] javafx, socket programming, and threads

查看:145
本文介绍了javafx,套接字编程和线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是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:


  1. 将此插入到您的请求中

  1. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆