私はソケットプログラミングが初めてです。チュートリアルからクライアントが文字列をサーバーに送信し、サーバーが文字列を大文字に変換してクライアントに返すJavaサーバークライアントコードをコピーしました。ソケットプログラミングでreadLine()にコードが詰まっています
大文字にする文字列を入力するJTextFieldと、大文字の文字列の出力を示すJTextAreaがあります。
しかし、問題は私がJTextFieldに入力を与えて、コードを入力するとハングすることです。デバッグでは、クライアントがreadLine()でサーバーから送信された大文字の文字列を読み取ろうとしたときにコードがハングすることが判明しました。
私はそれを取り除く方法を知りません。 Stack Overflowでいくつか似たような質問を読んだが解決策を試したが、望みはなかった。
Serverコード:
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();
}
}
あなたのコードには、「すべての改行後に出力がフラッシュされるようにする」というコメントがあります。私にとって、あなたは出力を洗い流すようには見えません。 – Davatar
PrintWriterのコンストラクタでautoflushをtrueに設定しました。 println()に遭遇すると、出力はフラッシュされます。しかし、出力を手動でフラッシュするout.flush()も追加しました。変更は発生しませんでした。 :( –