如何为Java应用程序提供网络功能?

如何为Java应用程序提供网络功能?,java,multithreading,servlets,thread-safety,Java,Multithreading,Servlets,Thread Safety,我有一个Java应用程序,可以输入图像,提供许多选项来编辑它们(裁剪、调整大小),然后将它们导出到本地存储 我目前正在尝试使用java.net将服务器连接到此应用程序,但由于我以前从未这样做,因此遇到了一些问题 我在GUI上有一个按钮可以激活服务器,这样应用程序就可以接收命令——问题是服务器使用的while循环在与客户端断开连接之前不会停止,这意味着程序在此之前无法运行。我假设它需要创建一个新线程,但是如何在不创建新实例的情况下向应用程序发送命令呢 我想通过服务器将图像从客户端发送到应用程序。客

我有一个Java应用程序,可以输入图像,提供许多选项来编辑它们(裁剪、调整大小),然后将它们导出到本地存储

我目前正在尝试使用java.net将服务器连接到此应用程序,但由于我以前从未这样做,因此遇到了一些问题

  • 我在GUI上有一个按钮可以激活服务器,这样应用程序就可以接收命令——问题是服务器使用的while循环在与客户端断开连接之前不会停止,这意味着程序在此之前无法运行。我假设它需要创建一个新线程,但是如何在不创建新实例的情况下向应用程序发送命令呢
  • 我想通过服务器将图像从客户端发送到应用程序。客户端当前正在使用JFileChooser拾取图像,但如何将其发送到流下并在另一端重新创建
  • 我的代码只是这个和的一个修改版本。它只是删除了echo特性,并根据客户端发送的字符串运行一个方法。(例如,客户端向服务器发送“open”-服务器运行open(){}方法

    编辑: 代码:

    这是服务器代码。ImageGUI是包含所有命令的GUI,包含openImage方法。 专用int端口号=8888

    public Server() {
    
        try (
        // Create Server socket
        ServerSocket theServer = new ServerSocket(portNumber);
                // Create socket for client
                Socket clientSocket = theServer.accept();
                // Use to write to client
                PrintWriter out = new PrintWriter(
                        clientSocket.getOutputStream(), true);
                // Used to read from client
                BufferedReader in = new BufferedReader(new InputStreamReader(
                        clientSocket.getInputStream()));) {
            // Waits for Client commands
            String clientCommand;
            while ((clientCommand = in.readLine()) != null) {
                if (clientCommand.contains("open")) {
                    // Runs open method in ImageGUI
                    new ImageGUI().openImage(); // I don't want this because it
                                                // will create another GUI
                                                // I want to run the openImage()
                                                // in the GUI already open
                }
            }
    
        } catch (IOException e) {
            e.printStackTrace();
        }
    
    }
    
  • 您可以使用共享命令发送和使用命令

    BlockingQueue是线程安全的。使用
    take()
    使服务器等待下一个命令,并使用主线程中的
    add()
    将命令添加到队列中

    然后可以使用类、枚举甚至字符串来表示命令,并将它们从主线程发送到服务器线程

  • 要发送图像,请从客户端(
    echoSocket.getOutputStream()
    )使用
    OutputStream
    )写入数据。服务器端,使用
    InputStream
    clientSocket.getInputStream()
    )接收数据

    例如:

    // Client side
    int returnVal = chooser.showOpenDialog(parent);
    if(returnVal == JFileChooser.APPROVE_OPTION) {
        File imageFile = chooser.getSelectedFile();
    
        try(FileInputStream imageInputStream = new FileInputStream(imageFile);
            OutputStream serverOutputStream = echoSocket.getOutputStream()) {
            int[] buffer = new int[1024];
            int readCount = imageInputStream.read(buffer);
            while(readCount > 0) {
                serverOutputStream.write(buffer, 0, readCount);
                readCount = imageInputStream.read(buffer);
            }
        }
    }
    
    以及:


  • 您可能希望在自己的线程中运行服务器的
    accept()
    循环

    您的服务器GUI的“启动服务器”按钮将启动此线程。请确保您还有一个“停止服务器”按钮,用于通知服务器线程退出。当用户退出应用程序时,也会通知服务器线程退出

    您需要决定发送图像的协议

    它可以像将图像文件中的字节压入套接字一样简单,然后关闭套接字——也可以是更复杂的事情,比如将字节块包装在标头中,说明数据包的大小、用途等


    或者它可能是其他人发明的一个预先存在的协议-在这种情况下,您可以使用库实现。许多人会使用HTTP来实现此目的。

    但是我如何在不创建新实例的情况下向应用程序发送命令呢?我在代码中添加了一条注释来解释我的意思。谢谢,我还有几条建议向上提问。图像正在以OpenCV的Mat格式编辑,但使用BuffereImage显示,您建议使用什么方法传输图像?如何使按钮停止服务器?单击按钮时,调用serverThread.stop()。任何服务器实现的适当示例都会有一个stop()方法。至于从BuffereImage获取要写入网络的内容,请使用与写入文件相同的方法,但不要使用FileOutputStream,而是写入您选择的任何协议。谢谢,因此我需要先初始化线程,然后启动它,并在单击按钮时停止它。因为我是在按下按钮时创建它的按钮在你初始化它的时候并不重要,只要它在你启动它之前!
    
    // Server side
    File folder = new File("/tmp/");
    File imageFile = new File(folder, "image.jpg");
    
    try(InputStream clientInputStream = clientSocket.getInputStream();
            FileOutputStream imageOutputStream = new FileOutputStream(imageFile)) {
            int[] buffer = new int[1024];
            int readCount = clientInputStream.read(buffer);
            while(readCount > 0) {
                imageOutputStream.write(buffer, 0, readCount);
                readCount = clientInputStream.read(buffer);
            }
        }
    }