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

时间:2014-02-19 15:38:20

标签: java multithreading servlets thread-safety

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

我目前正尝试使用java.net将服务器连接到此应用程序,但运行到几个问题,因为我以前从未这样做过。

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

    修改: 代码:

    这是服务器代码。 ImageGUI是包含所有命令的GUI,并保存openImage方法。     private int portNumber = 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();
        }
    
    }
    

2 个答案:

答案 0 :(得分:0)

  1. 您可以使用共享BlockingQueue来发送和使用命令。

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

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

  2. 要发送图像,请使用客户端OutputStreamechoSocket.getOutputStream())来写入数据。服务器端,使用InputStreamclientSocket.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);
            }
        }
    }
    

    // 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);
            }
        }
    }
    

答案 1 :(得分:0)

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

您的服务器GUI的“启动服务器”按钮将启动此线程。确保您还有一个“停止服务器”按钮,告诉服务器线程退出。还告诉服务器线程在用户退出应用程序时退出。

您需要决定使用协议来发送图片。

它可以简单到将图像文件中的字节从套接字向下推,然后关闭套接字 - 或者它可能是更复杂的东西,比如在头文件中包装大块的字节,说明数据包的大小,是什么它是等等。

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