Java Server在关闭后发送消息客户端

时间:2013-10-23 21:44:55

标签: 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 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);
       }
    }
  }
}

1 个答案:

答案 0 :(得分:4)

您有Swing线程问题。您的while (true)阻止Swing事件线程冻结您的程序。阅读后台线程的使用,特别是SwingWorker线程,以便您可以避免此问题。从Concurrency in Swing Tutorial开始。

只有在用户输入内容后,您才开始阅读,然后一遍又一遍地向服务器发送相同的字符串。

我建议:

  • 使用后台线程或SwingWorker从客户端中的服务器读取。这应该在客户端的构造函数中设置,而不是在ActionListener中设置。
  • 确保在 Swing事件线程或EDT上附加到客户端的文本区域。 SwingWorker将通过发布/处理方法对帮助您完成此任务。
  • ActionListener应该更简单。它应该做的就是获取JTextField的文本并通过out将其发送到out.println(...)字段。
  • 同样,out.println("line " + 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);
  }
}

在Client构造函数中:

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