Java服务器在关闭客户端后发送消息
我需要一些关于这个代码的帮助。这是关于一个服务器,它假设将来自客户端的消息回显到客户端,并在客户端键入“BYE”后关闭。但消息仅在服务器关闭后出现在客户端上 如果我能找到这个问题的解决办法,我将不胜感激 这是服务器端的代码: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
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)
循环中,除非您希望反复向服务器发送相同的字符串。同样,这应该在ActionListener中,并且应该是一个一次性交易,不在循环中调用,而是仅在执行侦听器时调用while(true)
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)
循环中,除非您希望反复向服务器发送相同的字符串。同样,这应该在ActionListener中,并且应该是一个一次性交易,不在循环中调用,而是仅在执行侦听器时调用while(true)
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');
}