当前位置: 首页 > 知识库问答 >
问题:

在单独的线程上获取套接字数据,然后将其传递给主线程

元叶秋
2023-03-14

编辑了我的问题以进行澄清和编码:

我的目标是将我的String数据从我的后台线程传递到我的主应用程序线程。感谢任何帮助。

下面是创建主后台线程的代码。这是位于我的Server.java类

public class Server {

boolean isConnected = false;
Controller controller = new Controller();

public void startHost() {
    Thread host = new Thread(() -> {
        Controller controller = new Controller();
        ServerSocket server = null;

        try {
            server = new ServerSocket(GeneralConstants.applicationPort);

        } catch (BindException e2) {
            System.out.println("Port Already in Use!");

        } catch (IOException e) {
            //do nothing

        }

        while (true) {
            if (server == null) { break; }

            try {
                Socket client = server.accept();

                System.out.println("Client Connected: " + isConnected);

                if (!isConnected) {
                    controller.createClientHandler(client);
                    isConnected = true;
                    System.out.println("Client Connected: " + isConnected);
                }

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();

            }
        }
    });

    host.setDaemon(true);
    host.start();

}

下面是连接客户端时调用的代码,它位于我的 Controller.java类中。

    public synchronized void createClientHandler(Socket client) {
    boolean alreadyConnected = false;

    if (alreadyConnected) {
        //do NOT assign multiple threads for each client

    } else {
        ClientHandler handleClients = new ClientHandler("client", client);

    }

}

然后程序为我的客户机创建两个后台线程,一个管理接收消息,一个管理发送消息。

public ClientHandler(String name, Socket s) {
    clientSocket = s;
    clientName = name;

    receiveThread = new Thread(this::receive);
    sendThread = new Thread(this::send);

    connected = clientSocket.isConnected();

    receiveThread.start();
    sendThread.start();

}

然后,线程成功地创建了inputstream,并将对象传递给我的控制器。然后处理并获取一个字符串,将其赋给一个变量

public synchronized void handleReceivedPacket(String name, BufferedReader in) {
    try {
        data = in.readLine();
        System.out.println("Successfully assigned data to: " + data);

    } catch (IOException e) {
        System.out.println("Unable to read result data");

    }

}

如何从主线程访问我的String数据而不为空?

Aka:我可以打电话(或类似的电话)

controller.returnData();

从我的主应用程序。它要么返回null(还没有数据),要么返回我的数据。现在,它总是空的。

编辑,这实际上是调用控制器。returnData(){

我不想粘贴大量代码,因为害怕达到StackOverflow的代码限制,所以这是我的应用程序结构。

My JavaFX创建场景,并创建一个根gridpane,然后调用一个基于指定输入创建子grid pane的方法。也就是说,用户可以按下“主菜单”来调用我的方法setScene(),该方法删除当前的“子根”gridpane并创建一个“新”场景。现在,我有一个GameBoard.java类,它在按钮按下时,调用controller.returnData()

PassOption.setOnAction(event -> {
        System.out.println(controller.returnData());


    });

除了测试之外,没有其他功能目的。如果我能接收到数据,那么我就可以利用这些数据进行扩展。

共有1个答案

秦滨海
2023-03-14

开始思考设计。在网络应用程序中,您通常必须管理以下职责:

  1. 连接的客户端及其状态(连接状态、检测信号等)
  2. 从客户端接收的消息
  3. 要传输到客户端的消息

为了保持代码的整洁、可读性和可维护性,将这些职责分开是有意义的。

分离可以同时意味着两者,线程和类。

例如,您可以按如下方式实现它:

类客户端接受器负责打开套接字并接受客户端。客户端连接后,它会将进一步的工作委派给控制器,然后等待其他客户端:

public class ClientAcceptor implements Runnable {

    @Override
    public void run() {
        while (true) {
            ServerSocket server;
            try {
                server = new ServerSocket(1992);
                Socket client = server.accept();

                if (client.isConnected()) {
                    controller.createClientHandler(client);
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

控制器然后可以创建处理程序(如果控制器决定这样做,例如,它也可以拒绝客户端)。< code>ClientHandler类可能如下所示:

public class ClientHandler {
    private Thread receiveThread;
    private Thread sendThread;
    private boolean connected;
    private Socket clientSocket;
    private String clientName;
    private LinkedBlockingDeque<byte[]> sendQueue;

    public ClientHandler(String name, Socket s) {
        clientSocket = s;
        clientName = name;

        receiveThread = new Thread(() -> receive());
        sendThread = new Thread(() -> send());

        connected = clientSocket.isConnected();

        receiveThread.start();
        sendThread.start();
    }

    private void receive() {
        BufferedInputStream in = null;
        try {
            in = new BufferedInputStream(clientSocket.getInputStream());
        } catch (IOException e) {
            connected = false;
        }
        while (connected) {
            try {
                byte[] bytes = in.readAllBytes();
                if (bytes != null && bytes.length > 0) {
                    controller.handleReceivedPacket(clientName, bytes);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void send() {
        BufferedOutputStream out = null;
        try {
            out = new BufferedOutputStream(clientSocket.getOutputStream());
        } catch (IOException e) {
            connected = false;
        }
        while (connected) {
            byte[] toSend = sendQueue.getFirst();
            if (toSend != null && toSend.length > 0) {
                try {
                    out.write(toSend);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void send(byte[] packet) {
        sendQueue.add(packet);
    }

    public void close() {
        connected = false;
    }
}

< code>ClientHandler负责接收和发送数据。如果数据包到达,它会通知控制器,由控制器解析数据包。< code>ClientHandler还提供了一个公共API来发送数据(存储在队列中,由线程处理)和关闭连接。

上面的代码示例既没有经过测试,也没有完成。把它作为一个起点。

 类似资料:
  • 我想从可运行线程抛出异常,但不可能从线程抛出它,所以我们可以将chlild线程的状态(任何异常)传递给父线程吗?. 我读到过thread.join(),但在这种情况下,父线程会一直等到子线程完成执行。 在我的例子中,我的父线程在一段时间后逐个启动线程,但当任何线程抛出异常时,它应该将失败通知paent,以便父线程不会启动其他线程。 有什么方法可以实现吗?谁能帮我解决这个问题。

  • 问题内容: 我正在编写的应用程序在某个阶段会生成一个ArrayList of Characters。在此阶段,我正在尝试创建一个线程来处理此ArrayList。问题是如何将这个ArrayList传递给线程 描述代码: ProcessList的描述性代码: 我的问题是:如何在run()中传递和访问aList? 问题答案: 您可以简单地传递给的构造函数,该构造函数可以保留引用,直到需要它为止: 注意:

  • 我有一个名为“bluetoothIn”的处理程序,我想使用HandlerThread类将其传递给一个单独的循环器,该类将提供循环器。然而,我需要将结果从“handleMessage(Message msg)”发回UI线程,因为我不能修改除主线程之外的其他线程的UI元素。 这是我的代码:

  • 根据http://wiki.apache.org/jmeter/JMeterFAQ我应该能够在jmeter Gui中指定jmeter测试计划的用户/线程数,如下所示: 其中defaultvalue可以是1,2,3,无论什么。。。 当我尝试这样做时,我的测试甚至没有开始。 有什么提示吗? 谢谢

  • 本文向大家介绍C#程序将参数传递给线程,包括了C#程序将参数传递给线程的使用技巧和注意事项,需要的朋友参考一下 要使用线程,请在代码中添加以下命名空间- 首先,您需要在C#中创建一个新线程- 上面,threadDemo是我们的线程函数。 现在将参数传递给线程- 上面设置的参数是- 示例 让我们看完整的代码,以将参数传递给C#中的线程。 输出结果

  • 问题内容: 我正在Android中编写一个活动,用户可以在其中修改SQL数据库。用户界面由一个EditText(用户在其中输入名称)和一个Seekbar(用户在其中输入用户的吸引力)组成。在下面有很多按钮:添加,编辑,查看,删除。 当用户单击“编辑”按钮时,将显示一个输入对话框,要求用户输入记录号。完成后,将加载该记录。 我遇到的问题是,将显示输入对话框,并且当用户输入记录号时,其余的编辑方法将继