[英]Code stucks in readLine() in socket programming
我是套接字編程的新手。 我從教程中復制了Java服務器客戶端代碼,在該教程中,客戶端將字符串發送到服務器,服務器將字符串大寫並將其發送回客戶端。
我有一個JTextField,其中輸入了要大寫的字符串,還有一個JTextArea,其中顯示了大寫的字符串輸出。
但是問題是當我在JTextField中輸入內容並按Enter時,代碼掛起。 通過調試,我發現當客戶端嘗試使用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();
}
}
您的問題是在客戶端。 替換方法代碼
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");
}
}
您只需要遍歷循環兩次,因為歡迎消息是兩行而不是三行。
通信始終需要同步。 如果從服務器發送兩行,則在發送內容之前,需要在客戶端上閱讀兩行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.