疑问代码部分:
/************************************/
//通常来说run()中的代码,有个无穷循环,保证持续监听,似乎以下代码不
//能做到,因为(input = in.readLine()) != null很容易满足,导致该线程
//结束。
while((input = in.readLine()) != null) {
if(input.indexOf(magic) != -1 && connectSound != null)
{
connectSound.play();
sendMessage("Congratulations "+student+" you sent the passphrase!\n");
System.out.println(student+" sent the passphrase!");
}
else ChatServer.this.sendToAllClients(input+"\n");
}
/************************************/
//通常来说run()中的代码,有个无穷循环,保证持续监听,似乎以下代码不
//能做到,因为(input = in.readLine()) != null很容易满足,导致该线程
//结束。
while((input = in.readLine()) != null) {
if(input.indexOf(magic) != -1 && connectSound != null)
{
connectSound.play();
sendMessage("Congratulations "+student+" you sent the passphrase!\n");
System.out.println(student+" sent the passphrase!");
}
else ChatServer.this.sendToAllClients(input+"\n");
}
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;public class ChatClient { private final String DEFAULT_SERVER_IP = "127.0.0.1";
private final int DEFAULT_SERVER_PORT = 2000; private String serverIP = DEFAULT_SERVER_IP;
private int serverPort = DEFAULT_SERVER_PORT; private Socket connection = null;
private BufferedReader serverIn = null;
private PrintStream serverOut = null; private TextArea output;
private TextField input;
private Button sendButton;
private Button quitButton;
private Choice usernames;
private MenuItem aboutMenuItem;
private MenuItem quitMenuItem;
private Dialog aboutDialog; public ChatClient() {
output = new TextArea(10,50);
input = new TextField(50);
sendButton = new Button("Send");
quitButton = new Button("Quit");
usernames = new Choice();
aboutMenuItem = new MenuItem("About");
quitMenuItem = new MenuItem("Quit"); // initialize server IP and port information
String serverIP = System.getProperty("serverip");
if(serverIP != null) this.serverIP = serverIP;
String serverPort = System.getProperty("serverport");
if(serverPort != null) this.serverPort = Integer.parseInt(serverPort);
} public void launchFrame() {
Frame frame = new Frame("Chat Room"); frame.setLayout(new BorderLayout()); frame.add(output,BorderLayout.WEST);
frame.add(input,BorderLayout.SOUTH); usernames.add("Grand Poobah");
usernames.add("The Man");
usernames.add("Java Geek"); Panel p1 = new Panel();
p1.add(sendButton);
p1.add(quitButton);
p1.add(usernames);
frame.add(p1,BorderLayout.CENTER); MenuBar mb = new MenuBar();
Menu file = new Menu("File");
file.add(quitMenuItem);
Menu help = new Menu("Help");
help.add(aboutMenuItem);
mb.add(file);
mb.setHelpMenu(help);
frame.setMenuBar(mb); // Create the aboutDialog once, it will be reused later
aboutDialog = new AboutDialog(frame,"About",true); // Attach listener to the appropriate components
sendButton.addActionListener(new SendHandler());
frame.addWindowListener(new CloseHandler());
input.addActionListener(new InputHandler());
// Use an anonymous inner class for variety.
quitButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
// Attach listeners to menu items
quitMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
aboutMenuItem.addActionListener(new AboutHandler()); doConnect(); frame.setSize(510,210);
frame.setVisible(true);
} private void doConnect() {
try {
connection = new Socket(serverIP,serverPort);
serverIn =
new BufferedReader(new InputStreamReader(connection.getInputStream()));
serverOut = new PrintStream(connection.getOutputStream());
Thread t = new Thread(new RemoteReader());
t.start();
}
catch(Exception e) {
System.out.println("Unable to connect to server!");
e.printStackTrace();
}
}
private void copyText() {
String text = input.getText();
serverOut.println(usernames.getSelectedItem()+": "+text);
input.setText("");
} private class SendHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
copyText();
}
} private class CloseHandler extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
private class InputHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
copyText();
}
} private class AboutHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
aboutDialog.setVisible(true);
}
} private class AboutDialog extends Dialog implements ActionListener {
public AboutDialog(Frame parent, String title, boolean modal) {
super(parent,title,modal);
add(new Label("The ChatClient is a neat tool that allows you to talk " +
"to other ChatClients via a ChatServer"),BorderLayout.NORTH);
Button b = new Button("OK");
add(b,BorderLayout.SOUTH);
pack();
b.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
setVisible(false);
}
} private class RemoteReader implements Runnable {
private boolean keepListening = true; public void run() {
while(keepListening == true) {
try {
String nextLine = serverIn.readLine();
output.append(nextLine+"\n");
}
catch(Exception e) {
keepListening = false;
System.out.println("Error while reading from server.");
e.printStackTrace();
}
}
}
} public static void main(String[] args) {
ChatClient c = new ChatClient();
c.launchFrame();
}
}
“input = in.readLine()) != null很容易满足,导致该线程结束。”
BufferedReader.readLine()只有在读到流结束符时才返回null,这只有客户端的输出流调用finish()或者close()方法,你才能读到。注意:用户仅仅敲击回车键,那in.readLine()读取的是回车苻,不是流结束符。