Java Server 关闭后发送消息客户端 [英] Java Server sending messages client after closing
问题描述
我需要有关此代码的帮助.它是关于一个服务器,它假设将来自客户端的消息回显到客户端并在客户端键入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 viaout.println(...)
. - Again, do not have
out.println("line " + sms);
inside of awhile (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屋!