简体   繁体   English

使用 Socket 的简单聊天应用程序

[英]simple chat application using Socket

I am trying to create a simple chat application want to send a message from one client to another/ or between client and server however my message is not being sent.我正在尝试创建一个简单的聊天应用程序,希望将消息从一个客户端发送到另一个/或客户端和服务器之间,但是我的消息没有被发送。 I am not sure about the port(8080) here as well as I copied from the internet.我不确定这里的端口(8080)以及我从互联网上复制的。 could anyone please help me what I am doing wrong?谁能帮助我我做错了什么? 在此处输入图像描述 Client.java Main Client.java 主要

  {
   con = new Socket("192.168.0.1", 8080);
     while (true) {
        try {
            
            DataInputStream input = new DataInputStream(con.getInputStream());
            String string = input.readUTF();
            textArea.setText(textArea.getText() + "\n" + "Server: " + string);
        } catch (Exception ev) {
             textArea.setText(textArea.getText()+" \n" +"Network issues ");

             try {
                    Thread.sleep(2000);
                    System.exit(0);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
        }
        
            

    }

} }

 private void btnNewButtonActionPerformed(java.awt.event.ActionEvent evt) {                                             
    if (textField.getText().equals("")) {
JOptionPane.showMessageDialog(null, "You cannot send an empty message!");
            }else  {
                textArea.setText(textArea.getText() + "\n" + "Client : " + textField.getText());
    try {
                    DataOutputStream output = new DataOutputStream(con.getOutputStream());
                    output.writeUTF(textField.getText());
                } catch (IOException e1) {
                    textArea.setText(textArea.getText() + "\n " + " Network issues");
                    try {
                        Thread.sleep(2000);
                        System.exit(0);
                    } catch (InterruptedException e2) {
                        e2.printStackTrace();
                    }

                }
                textField.setText("");
            }

Server.Java服务器.Java

private  void serverConnection() throws IOException {
    System.out.println("Test");
    server = new ServerSocket(8080);
    
     con = server.accept();
     lblNewLabel_2.setText("Client found !");
        lblNewLabel_2.setForeground(new Color(0, 0, 128));
     while (true) {
        try {
            
            DataInputStream input = new DataInputStream(con.getInputStream());
            String string = input.readUTF();
            textArea.setText(textArea.getText() + "\n " + "Client: " + string);
                            System.out.println(string);
        } catch (Exception ev) {
             textArea.setText(textArea.getText()+" \n" +"Network issues ");
             
                try {
                    Thread.sleep(2000);
                    System.exit(0);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
        }

    }
}

Swing is not thread and is single threaded. Swing 不是螺纹,是单螺纹。

This means that you should not update the UI (or some state the UI depends on) from outside the context of the Event Dispatching Thread and you should not perform any long running or blocking operations from within the context of the EDT.这意味着您不应从事件调度线程的上下文之外更新 UI(或 UI 所依赖的某些 state),并且不应从 EDT 的上下文中执行任何长时间运行或阻塞操作。

Start by having a look at Concurrency in Swing for more details.首先查看Swing 中的并发以了解更多详细信息。

Once solution might be to use a SwingWorker .一旦解决方案可能是使用SwingWorker This allows you to perform long running or blocking operations within the context of their own threads, but provides a simple way to signal to the UI that changes have occurred safely.这允许您在它们自己的线程的上下文中执行长时间运行或阻塞操作,但提供了一种简单的方法来向 UI 发出信号表明更改已安全发生。 See Worker Threads and SwingWorker for more details.有关更多详细信息,请参阅工作线程和 SwingWorker

The following is a VERY basic example.以下是一个非常基本的示例。 It's self contained, so the the code can act as either the client or server.它是自包含的,因此代码可以充当客户端或服务器。 This is tied to localhost , so you will need to run two instances locally.这与localhost相关联,因此您需要在本地运行两个实例。

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingWorker;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private ReadMessageWorker readWorker;

        private DataInputStream inputStream;
        private DataOutputStream outputStream;

        private ServerSocket serverSocket;
        private Socket socket;

        private JTextField messageField;
        private JTextArea messageArea;

        private JButton startServerButton;
        private JButton startClientButton;
        private JButton shutDownButton;

        public TestPane() {
            setLayout(new BorderLayout());

            messageField = new JTextField(10);
            messageArea = new JTextArea(10, 20);

            messageField.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    try {
                        String text = messageField.getText();
                        outputStream.writeUTF(text);
                        appendMessage(text);
                        messageField.setText(null);
                    } catch (IOException ex) {
                        Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
                        JOptionPane.showMessageDialog(TestPane.this, "Could not send message", "Error", JOptionPane.ERROR_MESSAGE);
                    }
                }
            });

            add(new JScrollPane(messageArea));
            add(messageField, BorderLayout.NORTH);

            startServerButton = new JButton("Start server");
            startClientButton = new JButton("Start client");
            shutDownButton = new JButton("Shutdown");
            shutDownButton.setEnabled(false);

            JPanel actionsPanel = new JPanel();
            actionsPanel.add(startServerButton);
            actionsPanel.add(startClientButton);
            actionsPanel.add(shutDownButton);

            add(actionsPanel, BorderLayout.SOUTH);

            startServerButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            createServer();
                        }
                    }).start();
                }
            });
            startClientButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            createClient();
                        }
                    }).start();
                }
            });
            shutDownButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    shutdown();
                }
            });
        }

        protected void didStartServer() {
            if (!EventQueue.isDispatchThread()) {
                EventQueue.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        didStartServer();
                    }
                });
                return;
            }

            startServerButton.setEnabled(false);
            startClientButton.setEnabled(false);
            shutDownButton.setEnabled(true);
        }

        protected void didStartClient() {
            if (!EventQueue.isDispatchThread()) {
                EventQueue.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        didStartClient();
                    }
                });
                return;
            }
            startServerButton.setEnabled(false);
            startClientButton.setEnabled(false);
            shutDownButton.setEnabled(true);
        }

        protected void didShutdown() {
            if (!EventQueue.isDispatchThread()) {
                EventQueue.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        didShutdown();
                    }
                });
                return;
            }
            startServerButton.setEnabled(true);
            startClientButton.setEnabled(true);
            shutDownButton.setEnabled(false);
        }

        protected void createClient() {
            try {
                didStartClient();
                appendMessage("Connecting to server");
                socket = new Socket("localhost", 8080);
                inputStream = new DataInputStream(socket.getInputStream());
                outputStream = new DataOutputStream(socket.getOutputStream());
                appendMessage("Connected to server\n");
                createMessageWorker();
            } catch (IOException ex) {
                Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
                JOptionPane.showMessageDialog(this, "Could not create client socket", "Error", JOptionPane.ERROR_MESSAGE);
            }
        }

        protected void createServer() {
            try {
                didStartServer();
                appendMessage("Starting server");
                serverSocket = new ServerSocket(8080);
                appendMessage("Waiting for client");
                Socket socket = serverSocket.accept();
                appendMessage("Client connected client\n");
                inputStream = new DataInputStream(socket.getInputStream());
                outputStream = new DataOutputStream(socket.getOutputStream());
                createMessageWorker();
            } catch (IOException ex) {
                Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
                JOptionPane.showMessageDialog(this, "Could not create server socket", "Error", JOptionPane.ERROR_MESSAGE);
            }
        }

        protected void createMessageWorker() {
            readWorker = new ReadMessageWorker(inputStream, new ReadMessageWorker.MessageListener() {
                @Override
                public void didRecieveMessage(String message) {
                    appendMessage(message);
                }
            });
            readWorker.addPropertyChangeListener(new PropertyChangeListener() {
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    System.out.println(readWorker.getState());
                    if (readWorker.getState() == SwingWorker.StateValue.DONE) {
                        try {
                            readWorker.get();
                        } catch (InterruptedException ex) {
                            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
                        } catch (ExecutionException ex) {
                            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
                            JOptionPane.showMessageDialog(TestPane.this, "Stopped reading due to error", "Error", JOptionPane.ERROR_MESSAGE);
                        }
                        shutdown();
                    }
                }
            });
            readWorker.execute();
        }

        protected void appendMessage(String message) {
            if (!EventQueue.isDispatchThread()) {
                EventQueue.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        appendMessage(message);
                    }
                });
                return;
            }
            messageArea.append(message + "\n");
        }

        protected void shutdown() {
            shutdownServer();
            shutdownSocket();
            appendMessage("\nShutdown completed\n");
            didShutdown();
        }

        protected void shutdownSocket() {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException ex) {
                }
            }
        }

        protected void shutdownServer() {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException ex) {
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException ex) {
                }
            }
            if (serverSocket != null) {
                try {
                    serverSocket.close();
                } catch (IOException ex) {
                }
            }
        }

    }

    public class ReadMessageWorker extends SwingWorker<Void, String> {

        public interface MessageListener {

            public void didRecieveMessage(String message);
        }

        private DataInputStream dataInputStream;
        private AtomicBoolean continueReading;
        private MessageListener listener;

        public ReadMessageWorker(DataInputStream dataInputStream, MessageListener listener) {
            this.dataInputStream = dataInputStream;
            this.listener = listener;
            continueReading = new AtomicBoolean(true);
        }

        @Override
        protected void process(List<String> chunks) {
            for (String message : chunks) {
                listener.didRecieveMessage(message);
            }
        }

        public void stopReading() {
            continueReading.set(false);
            try {
                dataInputStream.close();
            } catch (IOException ex) {
            }
        }

        @Override
        protected Void doInBackground() throws Exception {
            while (continueReading.get()) {
                String text = dataInputStream.readUTF();
                publish(text);
            }

            System.out.println("Read is now down...");

            return null;
        }

    }
}

Further enhancements might include setting up two SwingWorker s, one acting as the server and one acting as the client.进一步的增强可能包括设置两个SwingWorker ,一个充当服务器,一个充当客户端。 This would encapsulate the functionality of the createXxx methods.这将封装createXxx方法的功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM