Java Swing GUI 客户端和服务器聊天应用程序 TextArea 未更新 [英] Java Swing GUI Client and Server Chat App TextArea not updating

查看:26
本文介绍了Java Swing GUI 客户端和服务器聊天应用程序 TextArea 未更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Java 和用于 GUI 的 Swing 类开发聊天应用程序.

I am doing a Chat Application using Java and Swing class for GUI.

ChatServer 类将是从客户端接收消息并回显给所有客户端的服务器,但我只想为 2 个客户端进行聊天.

The ChatServer class will be the server receiving message from clients and echo back to all clients but I only intend to make the chat for 2 clients.

ChatClient 类既是客户端.它们在文本区域显示从服务器发送的内容.并将文本字段中的文本发送到服务器.

The ChatClient class is both of the client. They display what was sent from the server on the Text Area. And send texts in the Text Field to the server.

ChatClient 类

package chatclient;

import java.net.Socket;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;

public class ChatClient extends javax.swing.JFrame {


public ChatClient() {
    initComponents();
}

/**
 * This method is called from within the constructor to initialize the form.
 * WARNING: Do NOT modify this code. The content of this method is always
 * regenerated by the Form Editor.
 */
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">                          
private void initComponents() {

    scrollPane = new javax.swing.JScrollPane();
    textArea = new javax.swing.JTextArea();
    btnConnect = new javax.swing.JButton();
    btnDisconnect = new javax.swing.JButton();
    lblStatus = new javax.swing.JLabel();
    lblShowStatus = new javax.swing.JLabel();
    txtInput = new javax.swing.JTextField();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    setTitle("Chat Client A");

    textArea.setEditable(false);
    textArea.setColumns(20);
    textArea.setRows(5);
    textArea.setText("Welcome to the Chat Server. Type '/close' or Click 'Disconnect' to close.");
    textArea.setWrapStyleWord(true);
    textArea.setCaretPosition(textArea.getDocument().getLength());
    scrollPane.setViewportView(textArea);

    btnConnect.setText("Connect");
    btnConnect.setActionCommand("btnConnect");
    btnConnect.addMouseListener(new java.awt.event.MouseAdapter() {
        public void mouseClicked(java.awt.event.MouseEvent evt) {
            btnConnectMouseClicked(evt);
        }
    });

    btnDisconnect.setText("Disconnect");
    btnDisconnect.setActionCommand("btnDisconnect");
    btnDisconnect.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            btnDisconnectActionPerformed(evt);
        }
    });

    lblStatus.setText("Status: ");

    lblShowStatus.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
    lblShowStatus.setForeground(new java.awt.Color(255, 51, 51));
    lblShowStatus.setText("Disconnected");

    txtInput.setToolTipText("");
    txtInput.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            txtInputActionPerformed(evt);
        }
    });

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addContainerGap()
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(scrollPane)
                .addGroup(layout.createSequentialGroup()
                    .addComponent(btnConnect)
                    .addGap(18, 18, 18)
                    .addComponent(btnDisconnect)
                    .addGap(42, 42, 42)
                    .addComponent(lblStatus)
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                    .addComponent(lblShowStatus)
                    .addGap(0, 42, Short.MAX_VALUE))
                .addComponent(txtInput))
            .addContainerGap())
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addContainerGap()
            .addComponent(scrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 213, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 11, Short.MAX_VALUE)
            .addComponent(txtInput, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(btnConnect)
                .addComponent(btnDisconnect)
                .addComponent(lblStatus)
                .addComponent(lblShowStatus))
            .addContainerGap())
    );

    pack();
}// </editor-fold>                        

private void btnConnectMouseClicked(java.awt.event.MouseEvent evt) {                                        
    // TODO add your handling code here:
    lblShowStatus.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
    lblShowStatus.setForeground(new java.awt.Color(0, 204, 51));
    lblShowStatus.setText("Connected");

    // ADD CODES FOR CONNECTING TO CHAT SERVER

}                                       

private void btnDisconnectActionPerformed(java.awt.event.ActionEvent evt) {                                              
    // TODO add your handling code here:
    lblShowStatus.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
    lblShowStatus.setForeground(new java.awt.Color(255, 51, 51));
    lblShowStatus.setText("Disconnected");

    // ADD CODES FOR DISCONNECTING FROM CHAT SERVER

}                                             

private void txtInputActionPerformed(java.awt.event.ActionEvent evt) {                                         
    // TODO add your handling code here:
}                                        

/**
 * @param args the command line arguments
 */
public static void main(String args[]) {
    /* Set the Nimbus look and feel */
    //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
    /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
     * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
     */
    try {
        for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
                javax.swing.UIManager.setLookAndFeel(info.getClassName());
                break;
            }
        }
    } catch (ClassNotFoundException ex) {
        java.util.logging.Logger.getLogger(ChatClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (InstantiationException ex) {
        java.util.logging.Logger.getLogger(ChatClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex) {
        java.util.logging.Logger.getLogger(ChatClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (javax.swing.UnsupportedLookAndFeelException ex) {
        java.util.logging.Logger.getLogger(ChatClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    }
    //</editor-fold>      

    /* Create and display the form */
    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            new ChatClient().setVisible(true);
        }
    });

    String input = "", serverInput = "";
    String host = "localhost";
    int port = 1337;
    Socket client;

    // updateTextArea("TEST UPDATE");

    try {
        client = new Socket(host, port);
        System.out.println("Connected to Server!");

        DataInputStream in = new DataInputStream(client.getInputStream());
        DataOutputStream out = new DataOutputStream(client.getOutputStream());

        System.out.println("Before setting text area");
        updateTextArea("trying to update");

        do {
            // HANDLE INPUT PART HERE
            serverInput = in.readUTF();


            if(serverInput != null) {
                System.out.println("Reached here");
                System.out.println(serverInput);
                updateTextArea(serverInput); 
            }

        } while(!input.equals("/close"));
        System.out.println("Program closed");
    }    

    catch(Exception exc) {
        System.err.println(exc.getMessage());
    }


}

private static void updateTextArea(String temp) {
    textArea.setText(textArea.getText() + "
" + temp + "
");
    textArea.setCaretPosition(textArea.getDocument().getLength());
}

// Variables declaration - do not modify                     
private javax.swing.JButton btnConnect;
private javax.swing.JButton btnDisconnect;
private javax.swing.JLabel lblShowStatus;
private javax.swing.JLabel lblStatus;
private javax.swing.JScrollPane scrollPane;
private static javax.swing.JTextArea textArea;
private javax.swing.JTextField txtInput;
// End of variables declaration                   
}

ChatServer 类

package chatserver;

import java.io.BufferedReader;
import java.io.InputStreamReader;
// for testing
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 *
 * @author wacats
 */
public class ChatServer {
public static void main(String args[]) {
    int port = 1337;

    try {
        ServerSocket server = new ServerSocket(port);
        String inMessage = "";

        while(true) {
            Socket clientA = server.accept();
            DataInputStream inA = new DataInputStream(clientA.getInputStream());
            DataOutputStream outA = new DataOutputStream(clientA.getOutputStream());
            // outA.writeUTF("Welcome to the Chat Server. Type '/close' or Click 'Disconnect' to close.");

            // for testing
            // BufferedReader user = new BufferedReader(new InputStreamReader(System.in));

            do {
                inMessage = inA.readUTF();

                outA.writeUTF("testing");

                if(inMessage != null) {
                   outA.writeUTF(inMessage); 
                }

            } while(!inMessage.equals("/close"));
            clientA.close();
        }



    }

    catch(Exception ex) {
        ex.printStackTrace();
    }
}
}

我对这个程序的流程的想法是:

My idea on the process of this program is:

  1. 启动聊天服务器
  2. 启动 ChatClient
  3. 当两个客户端都连接到服务器时,他们就可以开始聊天了.
  4. 按Enter"会将文本字段中的文本发送到服务器.
  5. 服务器会将文本广播给两个客户端.
  6. 客户端将更新文本区域,附加从服务器收到的文本.

推荐答案

基本问题是,textArea 当你尝试调用 updateTextArea 时为 nullcode>,这是因为 invokeLater 调用还没有执行和构建你的 UI,你基本上有一个竞争条件.

The basic problem is, textArea is null when you try and call updateTextArea, this is because the invokeLater call hasn't executed yet and constructed your UI, you basically have a race condition.

在 Swing 中处理 Socket 的正常方法是使用 SwingWorker

The normal way to deal with Sockets in Swing is, is to use a SwingWorker

查看 Swing 中的并发工作线程和 SwingWorker 了解更多详情.

Have a look at Concurrency in Swing and Worker Threads and SwingWorker for more details.

有多种方法可以解决您的问题.您可以使用 SwingWorker 从套接字读取文本并生成更新通知(通过 publish/process)方法,这是众所周知的作为观察者模式".这很好,因为它分离了您的代码并生成了一个更可重用的解决方案.

There are a number of ways you could solve you problem. You could use the SwingWorker to read the text from the socket and generate update notifications (through the publish/process) methods, this is commonly known as an "observer pattern". This is good as it de-couples your code and generates a more reusable solution.

这个类所做的只是从 Socket 读取文本,并从文本中生成 ActionEvent ,很简单.

All this class does is reads text from the Socket and generates ActionEvents from the text, simple.

public class SocketReader extends SwingWorker<Void, String> {

    private List<ActionListener> actionListeners;

    public SocketReader() {
        actionListeners = new ArrayList<>(25);
    }

    public void addActionListener(ActionListener listener) {
        actionListeners.add(listener);
    }

    public void removeActionListener(ActionListener listener) {
        actionListeners.remove(listener);
    }

    @Override
    protected Void doInBackground() throws Exception {
        System.out.println("Connected to Server!");

        try (DataInputStream in = new DataInputStream(SocketManager.INSTACNE.getInputStream())) {

            System.out.println("Before setting text area");

            String serverInput = null;
            do {
                // HANDLE INPUT PART HERE
                serverInput = in.readUTF();

                if (serverInput != null) {
                    System.out.println("Read " + serverInput);
                    publish(serverInput);
                }

            } while (!serverInput.equals("/close"));
            System.out.println("Program closed");
        }
        return null;
    }

    @Override
    protected void process(List<String> chunks) {
        for (String text : chunks) {
            ActionEvent evt = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, text);
            for (ActionListener listener : actionListeners) {
                listener.actionPerformed(evt);
            }
        }
    }

}

SocketWriter

这个简单的将文本写入Socket,很简单.从技术上讲,您不需要为此使用 SwingWorker,但我喜欢取消相对容易的事实

SocketWriter

This simple writes text to the Socket, simple. Technically, you don't need to use a SwingWorker for this, but I like the fact that it's relatively easy to cancel

public class SocketWriter extends SwingWorker<Void, Void> {

    private List<String> messages;
    private ReentrantLock lock;
    private Condition waitCon;

    public SocketWriter() {
        messages = Collections.synchronizedList(new ArrayList<String>(25));
        lock = new ReentrantLock();
        waitCon = lock.newCondition();
    }

    public void write(String text) {
        System.out.println("Write " + text);
        messages.add(text);
        try {
            lock.lock();
            waitCon.signalAll();
        } finally {
            lock.unlock();
        }
    }

    @Override
    protected Void doInBackground() throws Exception {
        try (DataOutputStream out = new DataOutputStream(SocketManager.INSTACNE.getOutputStream())) {
            while (!isCancelled()) {
                while (messages.isEmpty() && !isCancelled()) {
                    try {
                        lock.lock();
                        waitCon.await();
                    } finally {
                        lock.unlock();
                    }
                }
                List<String> cache = new ArrayList<>(messages);
                messages.clear();
                for (String text : cache) {
                    System.out.println("Send " + text);
                    out.writeUTF(text);
                }
            }
        }
        return null;
    }

}

SocketManager

好的,这对我来说有点矫枉过正,但我​​想要一个 Socket 的中央控制器,你不必使用单例,你可以简单地把它变成一个简单的类并通过对您的 ChatClientSocketReader/Writer 的引用,但是已经晚了,我很懒

SocketManager

Okay, this is slightly overkill on my part, but I want a central controller for the Socket, you don't have to use a singleton, you could simply make it a simple class and pass a reference of it to your ChatClient and on down to the SocketReader/Writer, but it's late and I'm lazy

public enum SocketManager {
    INSTACNE;

    private String host = "localhost";
    private int port = 1337;
    private Socket socket;

    public Socket open() throws IOException {
        if (socket != null) {
            close();
        }
        socket = new Socket(host, port);
        return socket;
    }

    public void close() throws IOException {
        if (socket == null) {
            return;
        }
        socket.close();
    }

    public boolean isOpen() {
        return socket != null
            && socket.isConnected()
            && !socket.isClosed()
            && !socket.isInputShutdown()
            && !socket.isOutputShutdown();
    }

    public InputStream getInputStream() throws IOException {
        Objects.requireNonNull(socket, "Socket is not open");
        return socket.getInputStream();
    }

    public OutputStream getOutputStream() throws IOException {
        Objects.requireNonNull(socket, "Socket is not open");
        return socket.getOutputStream();
    }
}

ChatClient

这一切都很棒,但您打算如何使用它?

ChatClient

That's all nice a awesome and all, but how are you suppose to use it?

基本上,您将在 ChatClient 中创建 SocketReaderSocketWriter 的实例,并附加一个 ActionListener 到阅读器并在触发时更新 JTextArea 并将您想要发送的文本发送到 SocketWriter,例如...

Will, very basically, you create an instance of SocketReader and SocketWriter in your ChatClient, you attach an ActionListener to the reader and update the JTextArea when it's triggered and send the text you want sent to the SocketWriter, for example...

public class ChatClient extends javax.swing.JFrame {

    public ChatClient() {
        initComponents();
        socketReader = new SocketReader();
        socketReader.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String text = e.getActionCommand();
                textArea.append(text);
                textArea.append("
");
                textArea.setCaretPosition(textArea.getDocument().getLength());
            }
        });
        socketReader.execute();

        socketWriter = new SocketWriter();
        socketWriter.execute();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        scrollPane = new javax.swing.JScrollPane();
        textArea = new javax.swing.JTextArea();
        btnConnect = new javax.swing.JButton();
        btnDisconnect = new javax.swing.JButton();
        lblStatus = new javax.swing.JLabel();
        lblShowStatus = new javax.swing.JLabel();
        txtInput = new javax.swing.JTextField();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Chat Client A");

        textArea.setEditable(false);
        textArea.setColumns(20);
        textArea.setRows(5);
        textArea.setText("Welcome to the Chat Server. Type '/close' or Click 'Disconnect' to close.");
        textArea.setWrapStyleWord(true);
        textArea.setCaretPosition(textArea.getDocument().getLength());
        scrollPane.setViewportView(textArea);

        btnConnect.setText("Connect");
        btnConnect.setActionCommand("btnConnect");
        btnConnect.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                btnConnectMouseClicked(evt);
            }
        });

        btnDisconnect.setText("Disconnect");
        btnDisconnect.setActionCommand("btnDisconnect");
        btnDisconnect.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnDisconnectActionPerformed(evt);
            }
        });

        lblStatus.setText("Status: ");

        lblShowStatus.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        lblShowStatus.setForeground(new java.awt.Color(255, 51, 51));
        lblShowStatus.setText("Disconnected");

        txtInput.setToolTipText("");
        txtInput.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                txtInputActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(scrollPane)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(btnConnect)
                        .addGap(18, 18, 18)
                        .addComponent(btnDisconnect)
                        .addGap(42, 42, 42)
                        .addComponent(lblStatus)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(lblShowStatus)
                        .addGap(0, 42, Short.MAX_VALUE))
                    .addComponent(txtInput))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(scrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 213, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 11, Short.MAX_VALUE)
                .addComponent(txtInput, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(btnConnect)
                    .addComponent(btnDisconnect)
                    .addComponent(lblStatus)
                    .addComponent(lblShowStatus))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>                        

    private void btnConnectMouseClicked(java.awt.event.MouseEvent evt) {
        // TODO add your handling code here:
        lblShowStatus.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        lblShowStatus.setForeground(new java.awt.Color(0, 204, 51));
        lblShowStatus.setText("Connected");

        // ADD CODES FOR CONNECTING TO CHAT SERVER
    }

    private void btnDisconnectActionPerformed(java.awt.event.ActionEvent evt) {
        // TODO add your handling code here:
        lblShowStatus.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        lblShowStatus.setForeground(new java.awt.Color(255, 51, 51));
        lblShowStatus.setText("Disconnected");

        // ADD CODES FOR DISCONNECTING FROM CHAT SERVER
    }

    private void txtInputActionPerformed(java.awt.event.ActionEvent evt) {
        if (SocketManager.INSTACNE.isOpen()) {
            socketWriter.write(txtInput.getText());
        } else {
            System.out.println("!! Not open");
        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {

        try {
            /* Set the Nimbus look and feel */
            //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
            /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
            * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
             */
            try {
                for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                    if ("Nimbus".equals(info.getName())) {
                        javax.swing.UIManager.setLookAndFeel(info.getClassName());
                        break;
                    }
                }
            } catch (ClassNotFoundException ex) {
                java.util.logging.Logger.getLogger(ChatClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            } catch (InstantiationException ex) {
                java.util.logging.Logger.getLogger(ChatClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            } catch (IllegalAccessException ex) {
                java.util.logging.Logger.getLogger(ChatClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            } catch (javax.swing.UnsupportedLookAndFeelException ex) {
                java.util.logging.Logger.getLogger(ChatClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            }
            //</editor-fold>

            SocketManager.INSTACNE.open();

            /* Create and display the form */
            java.awt.EventQueue.invokeLater(new Runnable() {
                public void run() {
                    new ChatClient().setVisible(true);
                }
            });

        } catch (IOException ex) {
            ex.printStackTrace();
        }
        //</editor-fold>      

    }

    private SocketWriter socketWriter;
    private SocketReader socketReader;

    // Variables declaration - do not modify                     
    private javax.swing.JButton btnConnect;
    private javax.swing.JButton btnDisconnect;
    private javax.swing.JLabel lblShowStatus;
    private javax.swing.JLabel lblStatus;
    private javax.swing.JScrollPane scrollPane;
    private javax.swing.JTextArea textArea;
    private javax.swing.JTextField txtInput;
    // End of variables declaration                   
}

您会注意到,我在 main 中使用了 SocketManager#open,抱歉,错过了连接"代码.我建议将其移至该方法;)

You'll note, I used SocketManager#open in the main, sorry, missed you "connect" code. I would suggest moving that to that method instead ;)

我没有对此做太多改变,但以防万一......

I didn't make to much of change to this, but just in case...

public class ChatServer {

    public static void main(String args[]) {
        int port = 1337;

        try {
            ServerSocket server = new ServerSocket(port);
            String inMessage = "";

            while (true) {
                System.out.println("Waiting");
                Socket clientA = server.accept();
                System.out.println("Connected");
                DataInputStream inA = new DataInputStream(clientA.getInputStream());
                DataOutputStream outA = new DataOutputStream(clientA.getOutputStream());
                // outA.writeUTF("Welcome to the Chat Server. Type '/close' or Click 'Disconnect' to close.");

                // for testing
                // BufferedReader user = new BufferedReader(new InputStreamReader(System.in));
                do {
                    inMessage = inA.readUTF();

                    if (inMessage != null) {
                        outA.writeUTF(inMessage);
                    }

                } while (!inMessage.equals("/close"));
                clientA.close();
            }

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

通常,当客户端连接时,您会启动一个新的 Thread 并让它处理客户端 Socket,但这不是我的重点.

Normally, when a client connects, you'd start a new Thread and have it process the client Socket, but that wasn't my focus.

因此,基于所有这些,您有很多阅读内容要赶上,包括 Java 中的并发性关于套接字的所有信息

So, based on all that, you have a lot of reading to catch up on, including Concurrency in Java and All About Sockets

这篇关于Java Swing GUI 客户端和服务器聊天应用程序 TextArea 未更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆