Java 桌面应用程序,在多个客户端和一个服务器之间具有持续通信。如何正确设置设备之间的通信?

Java desktop application with continuous communication between many clients and one server. How to properly set communication between devices?

提问人:Theodore 提问时间:2/28/2023 更新时间:2/28/2023 访问量:54

问:

我正在创建一个可以通过 Internet 与服务器通信的 javafx 应用程序,我需要澄清一下事情应该如何工作。

我在客户端和服务器之间使用 SSLSocket(以确保一定程度的安全性)。

在客户端和服务器中,我都在运行一个无限的 while 循环,以便它们彼此保持持续的通信。结婚

 SSLSocketFactory socketFactory = sslContext.getSocketFactory();
            this.socket = (SSLSocket) socketFactory.createSocket(this.host, this.port);
            this.socket.setEnabledProtocols(new String[] {"TLSv1.2"});
            this.socket.setEnabledCipherSuites(new String[] {"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"});
            this.writer = new PrintWriter(new OutputStreamWriter(this.socket.getOutputStream()));
            this.reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
...

public void run() {
        this.setSocket(); // creates the connection in another thread
        try{
            while(true){
                this.input = this.reader.readLine(); /* problem 2 */ 
                if(this.reader.ready()) { /* problem 1 */ 
                    this.input = this.reader.readLine();
                    System.out.println(this.input +"\n------------------------------------");
                }

                if(this.output != null) {
                    // If the writer has a message that is ready to send send it.
                    System.out.println("writing to server: " + this.output);
                    this.writer.println(this.output);
                    this.writer.flush();
                    this.setOutput(null); 
                }
            }
        } catch (IOException e){
            e.printStackTrace();
            System.out.println("broke");
        }
    }

现在我注意到这个实现的几个问题,我提出了一些解决方案。

  1. 我注意到 BufferedReader.ready() 方法在调用 BufferedReader.readLine() 并且有数据要读取之前不会返回 true。因此,我将 this.reader.readLine() 方法调用移到了 this.reader.ready() 行的正前方。

  2. 这导致 while 循环停止并等待 this.reader.readLine() 方法完成读取(它永远不会这样做,因为服务器不会向客户端发送任何数据(至少不是连续的 - 服务器在收到来自客户端的请求后将数据发送到客户端)。通过停止 while 循环,代码永远不会更新输出值,因此无法向服务器发送响应(即使已建立安全连接,也会有效地锁定客户端与服务器通信。

  3. 在对这个问题进行了一些简单的阅读后,我决定通过使用 NIO(非阻塞输入输出)通信来解决它,因为我的示例目前使用的是阻塞输入输出通信。但是在浏览了一些示例之后,设置看起来相当复杂,除非绝对必要,否则我不确定是否要花时间学习它。

  4. 这让我想到了另一种方法。如果我将 bufferedReader 和 PrintWriter 推到单独的线程上,那么读取器可以处于停止无限 while 循环中而不会阻塞写入器,从而有效地解决问题,同时允许在阻塞 io 设置中连续通信。

现在,在我实施任何这些解决方案之前,我想知道是否有任何理由反对实现 NIO 或只是将阻塞 io 操作推到单独的线程上。

有没有我没有考虑过的另一种方法?在专业环境中哪个更标准?

Java 安全 IO NIO 通信

评论

0赞 vmicrobio 2/28/2023
如果你想得到一个“快速”的结果,你可以使用单独的线程,但我会使用NIO,因为它是标准化的,而且效率更高

答: 暂无答案