Java服务器在关闭客户端后发送消息

Java服务器在关闭客户端后发送消息,java,swing,sockets,tcp,event-dispatch-thread,Java,Swing,Sockets,Tcp,Event Dispatch Thread,我需要一些关于这个代码的帮助。这是关于一个服务器,它假设将来自客户端的消息回显到客户端,并在客户端键入“BYE”后关闭。但消息仅在服务器关闭后出现在客户端上 如果我能找到这个问题的解决办法,我将不胜感激 这是服务器端的代码: import java.io.*; import java.net.*; import java.util.*; import java.awt.*; import javax.swing.*; public class EchoServer extends JFram

我需要一些关于这个代码的帮助。这是关于一个服务器,它假设将来自客户端的消息回显到客户端,并在客户端键入“BYE”后关闭。但消息仅在服务器关闭后出现在客户端上

如果我能找到这个问题的解决办法,我将不胜感激

这是服务器端的代码:

import java.io.*;
import java.net.*; 
import java.util.*;
import java.awt.*;
import javax.swing.*;

public class EchoServer extends JFrame{

   private JTextArea jta = new JTextArea();

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

public EchoServer(){

   setLayout(new BorderLayout());
   add(new JScrollPane(jta), BorderLayout.CENTER);

   setTitle("Server");
   setSize(500, 300);
   setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   setVisible(true);

   try {

     //Creating Server socket  

     ServerSocket s = new ServerSocket(5000);

    //Display messge to show the server has bean running
    jta.append("Echo Server Started" + '\n');
    /*This is a blocking Statement
    *The program comes to a stand still until the ACCEPT method returns
          */

    Socket incoming = s.accept(); 

    jta.append("Connected to: " + incoming.getInetAddress() +
                     " at port: " + incoming.getLocalPort() + '\n' + '\n'); 



    BufferedReader in 
      = new BufferedReader(new InputStreamReader(incoming.getInputStream())); 
    PrintWriter out 
       = new PrintWriter(incoming.getOutputStream(), true); 


    //Display welcome message

     out.println("Hi my SERVER. Enter BYE to exit."); 


     for (;;) {
       String str = in.readLine(); 
       if (str == null) {
         break; 
       } else {

          //Display information from Client  

          out.println("Echo: " + str); 


          jta.append("Received: " + str + '\n');

          if (str.trim().equals("BYE")) 
          break; 
      }
    }
    //incoming.close(); 
  } catch (Exception e) {
     jta.append("Error: " + e); 
    }

    jta.append("EchoServer stopped."); 
  }

}
这是客户端的代码:

import java.io.*;
import java.net.*; 
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;


public class Client extends JFrame {

private JTextField jtf = new JTextField();

private JTextArea jta = new JTextArea();

private BufferedReader in;
private PrintWriter out;

public static void main(String[] args){

    new Client();
}

public Client(){

    JPanel p = new JPanel();
    p.setLayout(new BorderLayout());
    p.add(new JLabel("Enter Text:"), BorderLayout.WEST);
    p.add(jtf, BorderLayout.CENTER);
    jtf.setHorizontalAlignment(JTextField.RIGHT);

    setLayout(new BorderLayout());
    add(p, BorderLayout.NORTH);
    add(new JScrollPane(jta), BorderLayout.CENTER);

    jtf.addActionListener(new TextFieldListener());

    setTitle("Client");
    setSize(500, 300);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);

    try {

        //creating a socket

        Socket socket= new Socket("localhost", 5000);


        in = new 
            BufferedReader(new InputStreamReader(socket.getInputStream()));

        out = new 
            PrintWriter(socket.getOutputStream(), true);

    }
    catch(IOException ex){
        jta.append(ex.toString() + '\n');
    }
}

private class TextFieldListener implements ActionListener {
    @Override

    public void actionPerformed(ActionEvent e){
       try{
          while (true){                

                String str= in.readLine();

                if (str == null) {

                    //break out of loop

                    break;
                } else {

                    //Display input from server
                    jta.append(str  + "\n");


                    /*enable user to in the text that 
                        will be sent ot the server
                    */
                    String sms = jtf.getText().trim();

                    if ("BYE".equals(sms)){

                        /*if the user types "BYE" send it to the server
                            and break out of the loop
                        */

                        out.println("BYE");

                        break;
                    }

                    //send messages to the server
                    out.println("line " + sms);

                } 
          }
       }
       catch (IOException ex) {
           System.err.println(ex);
       }
    }
  }
}

您有一个Swing线程问题。您的
while(true)
正在阻止Swing事件线程冻结您的程序。阅读背景线程的使用,特别是SwingWorker线程,这样可以避免这个问题。先从这个开始

您也只是在用户键入内容之后才开始阅读,然后一遍又一遍地将相同的字符串发送到服务器

我建议:

  • 使用后台线程或SwingWorker从客户端的服务器读取。这应该在客户端的构造函数中设置,而不是在ActionListener中设置
  • 确保在Swing事件线程或EDT上附加到客户端的文本区域。SwingWorker将通过发布/处理方法对帮助您完成这项工作
  • ActionListener应该简单得多。它所要做的就是获取JTextField的文本,并通过
    out.println(…)
    将其发送到您的
    out
    字段
  • 同样,不要有
    out.println(“行”+sms)
    while(true)
    循环中,除非您希望反复向服务器发送相同的字符串。同样,这应该在ActionListener中,并且应该是一个一次性交易,不在循环中调用,而是仅在执行侦听器时调用
例如,ActionListener可以简单到:

private class TextFieldListener implements ActionListener {
  @Override
  public void actionPerformed(ActionEvent e) {
     String sms = jtf.getText().trim();
     out.println("line " + sms);
  }
}
在客户端构造函数中:

  try {
     Socket socket = new Socket("localhost", 5000);
     in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

     // !!
     new Thread(new Runnable() {

        @Override
        public void run() {
           try {
              while (true) {
                 final String str = in.readLine();
                 if (str == null) {
                    break;
                 } else {

                    // ***** call Swing code on the Swing event thread:
                    SwingUtilities.invokeLater(new Runnable() {
                       public void run() {
                          jta.append(str + "\n");
                       }
                    });

                    // String sms = jtf.getText().trim();
                    // if ("BYE".equals(sms)) {
                    //    out.println("BYE");
                    //    break;
                    // }
                    // ***** don't call this here!!! *****
                    // out.println("line " + sms);
                 }
              }
           } catch (IOException ex) {
              System.err.println(ex);
           }
        }
     }).start();

     out = new PrintWriter(socket.getOutputStream(), true);
  } catch (IOException ex) {
     jta.append(ex.toString() + '\n');
  }

您有一个Swing线程问题。您的
while(true)
正在阻止Swing事件线程冻结您的程序。阅读背景线程的使用,特别是SwingWorker线程,这样可以避免这个问题。先从这个开始

您也只是在用户键入内容之后才开始阅读,然后一遍又一遍地将相同的字符串发送到服务器

我建议:

  • 使用后台线程或SwingWorker从客户端的服务器读取。这应该在客户端的构造函数中设置,而不是在ActionListener中设置
  • 确保在Swing事件线程或EDT上附加到客户端的文本区域。SwingWorker将通过发布/处理方法对帮助您完成这项工作
  • ActionListener应该简单得多。它所要做的就是获取JTextField的文本,并通过
    out.println(…)
    将其发送到您的
    out
    字段
  • 同样,不要有
    out.println(“行”+sms)
    while(true)
    循环中,除非您希望反复向服务器发送相同的字符串。同样,这应该在ActionListener中,并且应该是一个一次性交易,不在循环中调用,而是仅在执行侦听器时调用
例如,ActionListener可以简单到:

private class TextFieldListener implements ActionListener {
  @Override
  public void actionPerformed(ActionEvent e) {
     String sms = jtf.getText().trim();
     out.println("line " + sms);
  }
}
在客户端构造函数中:

  try {
     Socket socket = new Socket("localhost", 5000);
     in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

     // !!
     new Thread(new Runnable() {

        @Override
        public void run() {
           try {
              while (true) {
                 final String str = in.readLine();
                 if (str == null) {
                    break;
                 } else {

                    // ***** call Swing code on the Swing event thread:
                    SwingUtilities.invokeLater(new Runnable() {
                       public void run() {
                          jta.append(str + "\n");
                       }
                    });

                    // String sms = jtf.getText().trim();
                    // if ("BYE".equals(sms)) {
                    //    out.println("BYE");
                    //    break;
                    // }
                    // ***** don't call this here!!! *****
                    // out.println("line " + sms);
                 }
              }
           } catch (IOException ex) {
              System.err.println(ex);
           }
        }
     }).start();

     out = new PrintWriter(socket.getOutputStream(), true);
  } catch (IOException ex) {
     jta.append(ex.toString() + '\n');
  }