Java Server 关闭后发送消息客户端 [英] Java Server sending messages client after closing

查看:37
本文介绍了Java Server 关闭后发送消息客户端的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要有关此代码的帮助.它是关于一个服务器,它假设将来自客户端的消息回显到客户端并在客户端键入BYE"后关闭.但是消息只有在服务器关闭后才会出现在客户端.

I need some help with this code. It's about a Server that suppose to echo the messages from the client back to the client and close after the client types "BYE". But messages only appear on the client after the server is closed.

如果我能得到这个问题的解决方案,我将不胜感激

I will be grateful if I can get the solution to this problem

这是服务器端的代码:

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 线程,这样您就可以避免这个问题.从Swing 并发教程开始.

You have a Swing threading issue. Your while (true) is blocking the Swing event thread freezing your program. Read on use of background threads, in particular a SwingWorker thread so you can avoid this problem. Start with the Concurrency in Swing Tutorial.

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

You're also starting your reading only after the user types something, and then sending the same String to the server over and over.

我建议:

  • 在客户端使用后台线程或 SwingWorker 从服务器读取.这应该在客户端的构造函数中设置,而不是在 ActionListener 中.
  • 确保您在 Swing 事件线程或 EDT 上附加到客户端的文本区域.SwingWorker 将通过发布/处理方法对帮助您完成此操作.
  • ActionListener 应该简单得多.它应该做的就是获取 JTextField 的文本并通过 out.println(...) 将其发送到您的 out 字段.
  • 同样,在 while (true) 循环中不要有 out.println("line " + sms); ,除非你想发送相同的一遍又一遍地向服务器传递字符串.同样,这应该在 ActionListener 中,并且应该是一次性的,不是在循环中调用,而是仅在执行侦听器时调用.
  • Use a background thread or SwingWorker to read from the server in the client. This should be set up in the client's constructor, not in the ActionListener.
  • Make sure that you append to the client's text area on the Swing event thread or EDT. A SwingWorker will help you do this via the publish/process method pair.
  • The ActionListener should be much simpler. All it should do is get the JTextField's text and send it to your out field via out.println(...).
  • Again, do not have out.println("line " + sms); inside of a while (true) loop, not unless you want to send the same String to the server over and over and over again. Again, this should be in the ActionListener and should be a one shot deal, not called in a loop, but only when the listener is performed.

例如,ActionListener 可以很简单:

For example, the ActionListener could be as simple as:

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

这篇关于Java Server 关闭后发送消息客户端的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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