java - 在java中通过客户端服务器网络将进程输出打印到JTextArea

标签 java swing sockets

import java.io.*;
import java.net.*;
import java.io.FileInputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousCloseException;
import java.nio.channels.FileChannel;

class StreamCopier implements Runnable {
private InputStream in;
private BufferedOutputStream out;

public StreamCopier(InputStream in, BufferedOutputStream out) 
{
    this.in = in;
    this.out = out;
}

public void run() 
{
    try 
    {
        int n;
        byte[] buffer = new byte[4096];
        while ((n = in.read(buffer)) != -1) 
        {
            out.write(buffer, 0, n);
            out.flush();
        }
    }
    catch (IOException e) 
    {
        System.out.println(e);
    }
}
}

class InputCopier implements Runnable 
{

private BufferedInputStream in;
private OutputStream out;

public InputCopier(BufferedInputStream in, OutputStream out) 
{
    this.in = in;
    this.out = out;
}

public void run() 
{
    try 
    {
        int n;
        byte buffer[] = new byte[4096];
        while ((n = in.read(buffer)) != -1) 
        {
            out.write(buffer, 0, n);
            out.flush();
        }
        out.close();
    } 
    catch (AsynchronousCloseException e) 
    {
    }
    catch (IOException e) 
    {
        System.out.println(e);
    }
}
}

public class Test 
{
  private static Socket socket;

public static void main(String[] args)throws IOException, InterruptedException, NoSuchFieldException, IllegalAccessException
{
    try
    {
        ServerSocket serverSocket=new ServerSocket(5000);
        socket=serverSocket.accept();

        BufferedInputStream in=new BufferedInputStream(socket.getInputStream());
        BufferedOutputStream out=new BufferedOutputStream(socket.getOutputStream());
   //     BufferedOutputStream err=new BufferedOutputStream(socket.getErrorStream());
        Process process = Runtime.getRuntime().exec("java Hello");

        Thread outThread = new Thread(new StreamCopier(process.getInputStream(), out));
        outThread.start();

    //    Thread errThread = new Thread(new StreamCopier(process.getErrorStream(), err));
     //   errThread.start();

        Thread inThread = new Thread(new InputCopier(in, process.getOutputStream()));
        inThread.start();

        process.waitFor();
        System.in.close();
        outThread.join();
    //    errThread.join();
        inThread.join();
    }
     catch(Exception e)
    {
        e.printStackTrace();
    }
    finally
    {
        try
        {
            socket.close();
        }
        catch(Exception e)
        {
            System.out.println(e);
        }
    }
}
}

测试类包含服务器套接字程序

import java.io.*;
import java.net.*;

class User
{
private static Socket socket;

public static void main(String args[])
{
    try
    {
        socket = new Socket("localhost",5000);
        Thread t1 = new A(socket);
        t1.start();
        Thread t2 = new B(socket);
        t2.start();

        t1.join();
        t2.join();
    }
     catch(Exception e)
    {
        e.printStackTrace();
    }
    finally
    {
        try
        {
            socket.close();
        }
        catch(Exception e)
        {
            System.out.println(e);
        }
    }
}
}
class B extends Thread
{
Socket socket;
B(Socket socket)
{
    this.socket=socket;
}
public void run()
{
    try
    {
        BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
        InputStream in=System.in;
        int n;
         byte buffer[] = new byte[4096];
         while ((n = in.read(buffer)) != -1)
         {
            out.write(buffer, 0, n);
            out.flush();
         }
    }
    catch(Exception e)
    {}
}
}
class A extends Thread
{
Socket socket;
A(Socket socket)
{
    this.socket=socket;
}
public void run()
{
    try
    {
        BufferedInputStream in = new BufferedInputStream(socket.getInputStream());
        OutputStream out = System.out;

        int n;
        byte[] buffer = new byte[4096];
        while ((n = in.read(buffer)) != -1) 
        {
            out.write(buffer, 0, n);
            out.flush();
        }
    }
    catch(Exception e)
    {}
}
}

用户类包含客户端套接字程序。

程序的输出 Output of program

我想将进程的输出打印到 JTextArea 并通过 JTextField 将输入传递给进程。

用户界面代码。

import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JButton;


public class Client {

private JFrame frame;
private JTextField textField;

/**
 * Launch the application.
 */
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                Client window = new Client();
                window.frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the application.
 */
public Client() {
    initialize();
}

/**
 * Initialize the contents of the frame.
 */
private void initialize() {
    frame = new JFrame();
    frame.setBounds(100, 100, 450, 300);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().setLayout(null);

    JTextArea txtrTextAreaFor = new JTextArea();
    txtrTextAreaFor.setText("Text Area For Output of process");
    txtrTextAreaFor.setBounds(36, 11, 289, 143);
    frame.getContentPane().add(txtrTextAreaFor);

    textField = new JTextField();
    textField.setBounds(36, 165, 191, 43);
    frame.getContentPane().add(textField);
    textField.setColumns(10);

    JButton btnSubmit = new JButton("Submit");
    btnSubmit.setBounds(236, 185, 89, 23);
    frame.getContentPane().add(btnSubmit);
}
}

最佳答案

所以,我完全是凭空写出来的,没有经过测试,所以可能需要一些调整

Swing 是一个单线程框架,它也不是线程安全的。这意味着您不应该执行任何可能阻塞事件调度线程的操作,例如读取/写入Socket,并且永远不应该从事件调度线程外部更新 UI。

看看Concurrency in Swing了解更多详情。

现在,对此的解决方案很少,最简单的可能是使用 SwingWorker,它允许您在 EDT 之外在后台进行某种处理(长时间运行/阻塞)线程,但它提供了许多简单的方法将数据安全地同步回 UI。

参见Worker Threads and SwingWorker了解更多详情。

此示例对 WriteWorkerReadWorker 使用 SwingWorker,从技术上讲,您不需要使用 SwingWorker 用于写入操作,因为您并未真正与 UI 交互,但我这样做是因为它稍微简化了错误管理。

public class SocketThread implements Runnable {

    private String host;
    private int port;

    private JTextArea ta;

    private WriteWorker writeWorker;
    private ReadWorker readWorker;

    private CountDownLatch shutDownLatch;

    public SocketThread(String host, int port, JTextArea ta) {
        this.host = host;
        this.port = port;
        this.ta = ta;
    }

    public void write(String text) {
        if (writeWorker != null) {
            if (writeWorker.getState() == SwingWorker.StateValue.STARTED) {
                writeWorker.write(text);
            } else {
                throw new IllegalStateException("Write worker is not running");
            }
        } else {
            throw new NullPointerException("Write worker is nul");
        }
    }

    public void close() {
        if (writeWorker != null) {
            writeWorker.cancel(true);
        }
        if (readWorker != null) {
            readWorker.cancel(true);
        }

        // Force the CountDownLatch to release
        if (shutDownLatch != null) {
            shutDownLatch.countDown();
            shutDownLatch.countDown();
        }
    }

    @Override
    public void run() {
        try (Socket socket = new Socket(host, port)) {
            writeWorker = new WriteWorker(socket.getOutputStream());
            readWorker = new ReadWorker(socket.getInputStream(), ta);

            writeWorker.addPropertyChangeListener(new PropertyChangeHandler());
            readWorker.addPropertyChangeListener(new PropertyChangeHandler());

            writeWorker.execute();
            readWorker.execute();

            shutDownLatch = new CountDownLatch(2);
            shutDownLatch.await();
        } catch (IOException ex) {
            ex.printStackTrace();
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }

    protected class PropertyChangeHandler implements PropertyChangeListener {

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            SwingWorker worker = (SwingWorker) evt.getSource();
            if (worker.getState() == SwingWorker.StateValue.DONE) {
                shutDownLatch.countDown();

                // Not interested in the return value, only interested in the
                // exception if one was thrown...
                try {
                    worker.get();
                } catch (InterruptedException | ExecutionException ex) {
                    // Resync the error with the UI, probably using SwingUtilities.invokeLater
                    // and call some error handling method
                    ex.printStackTrace();
                }
            }
        }

    }

}

public class WriteWorker extends SwingWorker {

    private OutputStream os;

    private List<String> queue = new ArrayList<String>(25);
    private ReentrantLock queueLock = new ReentrantLock();
    private Condition queueCondition = queueLock.newCondition();

    public WriteWorker(OutputStream os) {
        this.os = os;
    }

    public void write(String text) {
        queueLock.lock();
        try {
            queue.add(text);
            queueCondition.signal();
        } finally {
            queueLock.unlock();
        }
    }

    @Override
    protected Object doInBackground() throws Exception {
        while (!isCancelled()) {
            String text = null;
            while (text == null && !isCancelled()) {
                queueLock.lock();
                try {
                    if (queue.isEmpty()) {
                        queueCondition.await();
                    }

                    if (!queue.isEmpty()) {
                        text = queue.remove(0);
                    }
                } finally {
                    queueLock.unlock();
                }
                if (text != null) {
                    os.write(text.getBytes());
                }
            }
        }
        return null;
    }

}

public class ReadWorker extends SwingWorker<Void, String> {

    private InputStream is;
    private JTextArea ta;

    public ReadWorker(InputStream is, JTextArea ta) {
        this.is = is;
        this.ta = ta;
    }

    @Override
    protected void process(List<String> chunks) {
        for (String text : chunks) {
            ta.append(text);
        }
    }

    @Override
    protected Void doInBackground() throws Exception {
        byte[] buffer = new byte[4096];
        int bytesRead = -1;
        while (!isCancelled() && (bytesRead = is.read(buffer)) != -1) {
            String text = new String(buffer, 0, bytesRead);
            publish(text);
        }
        return null;
    }

}

关于java - 在java中通过客户端服务器网络将进程输出打印到JTextArea,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60593207/

相关文章:

java - Android:BitmapFactory.decodeStream() 在第一次成功后返回 null

Java Swing : Add resources at run time

java - 使用 Java 从托管服务器到本地 PC 进行 HTTP 调用

ios - 应用程序终止时通知视频聊天应用程序

java - 获取 jDateChooser 日期到 jLabel

c - 在 Linux 上获取接口(interface)的 IP 地址

java - 获取 Hbase 中特定行的所有列值

java - 在 Spring Boot 中编写单元测试,但由于转换器类而出现错误

java - 如何设置 Intellij 在实例变量不存在 "this"时发出警报

java - 从容器中查找并检索组件