我是套接字编程的新手。我从教程中复制了一个java服务器客户端代码,其中客户端将字符串发送到服务器,服务器将字符串大写并将其发送回客户端。
我有一个JTextField,我输入要大写的字符串和一个显示大写字符串输出的JTextArea。
但问题是我在JTextField中输入输入并按下输入代码挂起。通过debuging我发现当客户端尝试读取服务器使用readLine()发送的大写字符串时代码挂起。
我不知道如何摆脱它。我已经在Stack Overflow中阅读了几个类似的问题并尝试了解决方案,但没有希望。
服务器代码:
public class CapitalizeServer {
/**
* @param args the command line arguments
* @throws java.io.IOException
*/
public static void main(String[] args) throws IOException {
System.out.println("The Capitalization Server is running");
int clientNumber = 0;
try (ServerSocket listener = new ServerSocket(1234)) {
while(true) {
new Capitalizer(listener.accept(), clientNumber++).start();
}
}
}
private static class Capitalizer extends Thread {
Socket socket;
int clientNumber;
public Capitalizer(Socket socket, int clientNumber) {
this.socket = socket;
this.clientNumber = clientNumber;
log("New connection with client# " + clientNumber + " at " + socket);
}
@Override
public void run() {
try {
// Decorate the streams so we can send characters
// and not just bytes. Ensure output is flushed
// after every newline.
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
// Send a welcome message to the client.
out.println("Hello, you are client # " + clientNumber + ".");
out.println("Enter a line with only a period to quit");
// Get messages from the client, line by line; return them capitalized
while(true) {
String input = in.readLine();
if(input == null || input.equals(".")) {
break;
}
//System.out.println("Coming input: " + input);
out.println(input.toUpperCase());
//System.out.println("UpperCase: " + input.toUpperCase());
}
} catch (IOException ex) {
log("Error handling client# " + clientNumber + ": " + ex );
} finally {
try {
socket.close();
} catch (IOException ex) {
log("Could not close a socket. What's going on?");
}
log("Connection with client# " + clientNumber + " closed");
}
}
/**
* Logs a simple message. In this case we just write the
* message to the server applications standard output.
*/
private void log(String message) {
System.out.println(message);
}
}
}
客户代码:
public class CapitalizeClient {
private BufferedReader in;
private PrintWriter out;
private JFrame frame = new JFrame("Capitalize Client");
private final JTextField dataField = new JTextField(40);
private final JTextArea messageArea = new JTextArea(8,60);
/**
* Constructs the client by laying out the GUI and registering a
* listener with the textField so that pressing Enter in the
* listener sends the textField contents to the server.
*/
public CapitalizeClient() {
// Layout GUI
messageArea.setEditable(false);
frame.getContentPane().add(dataField, "North");
frame.getContentPane().add(new JScrollPane(messageArea), "Center");
// Add Listeners
dataField.addActionListener(new ActionListener() {
/**
* Responds to pressing the enter key in the textField
* by sending the contents of the text field to the
* server and displaying the response from the server
* in the text area. If the response is "." we exit
* the whole application, which closes all sockets,
* streams and windows.
*/
@Override
public void actionPerformed(ActionEvent e) {
out.println(dataField.getText());
String response;
try {
// ******* The code stucks here *************
response = in.readLine();
if(response == null) {
System.exit(0);
}
} catch (IOException ex) {
response = "Error: " + ex;
}
messageArea.append(response + "\n");
dataField.selectAll();
}
});
}
public void connectToServer() throws IOException {
// Get the server address from a dialog box.
String serverAddress = JOptionPane.showInputDialog(frame, "Enter IP Address of the Server:" ,
"Welcome to the Capitalization Program", JOptionPane.QUESTION_MESSAGE);
// Make connection and initialize streams
Socket socket = new Socket(serverAddress, 1234);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
// Consume the initial welcoming messages from the server
for(int i=0; i < 3; i++) {
messageArea.append(in.readLine() + "\n");
}
}
public static void main(String[]args) throws IOException {
CapitalizeClient client = new CapitalizeClient();
client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
client.frame.pack();
client.frame.setVisible(true);
client.connectToServer();
}
}
答案 0 :(得分:4)
您的问题出在客户端。替换方法代码
public void connectToServer() throws IOException {
// Get the server address from a dialog box.
String serverAddress = JOptionPane.showInputDialog(frame, "Enter IP Address of the Server:",
"Welcome to the Capitalization Program", JOptionPane.QUESTION_MESSAGE);
// Make connection and initialize streams
Socket socket = new Socket(serverAddress, 1234);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
// Consume the initial welcoming messages from the server
for (int i = 0; i < 2; i++) {
messageArea.append(in.readLine() + "\n");
}
}
您只需要循环遍历循环两次,因为欢迎消息是两行而不是三行。
通信始终需要同步。如果从服务器发送两行,则需要在发送内容之前在客户端上读取两行。