Reputation: 1350
I have the following problem:
System.in
and sending it via SocketSystem.in
when a error occurs in itWhen I have a problem in method2, I have to press ENTER
twice, because, even it closing the socket, the readLine()
on method1 was already executed, so it first read the line for method1, then it takes the input for method2.
Edit: The method1 is constantly receiving messages from the socket and method2 is sending everything I type on console via Socket. But when the receive of messages fail, I want to just ask if the client wants to connect to other server, but the method1 already read the line, so the first time i type goes to the now useless method1, then the second line goes correctly to method2
What can I do in this case?
Observation: I know in the example I can make the reader as a class property. Just made this way to make it easier to understand
public class App {
public void method1() {
new Thread(() -> {
String line;
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
while (!socket.isClosed() && line = bufferedReader.readLine() != null) {
//Keeps reading from the System.in and sending to the Socket
}
}).start();
}
public void method2() {
try {
//Keeps receiving messages from the Socket
} catch (Exception e) {
socket.close();
String line;
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
line = bufferedReader.readLine();
//Asks if the user want to connect to other server
}
}
}
Upvotes: 0
Views: 91
Reputation: 408
There is no easy way to do that because System.in
is a bare InputStream, which is uninterruptible, unstoppable, and will block the caller until it is closed or EOF is reached.
One ugly solution is to create a new thread and stop the old thread. However, this requires using the deprecated Thread.stop()
method.
public class App {
private Thread sender;
private void stopSender() {
if (sender != null) {
sender.stop();
sender = null;
}
}
private void startSender() {
// stop previous sender if necessary
stopSender();
sender = new Thread(() -> String line;
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
while (!socket.isClosed() && line = bufferedReader.readLine() != null) {
//Keeps reading from the System.in and sending to the Socket
}
});
sender.start();
}
public void method2() {
try {
//Keeps receiving messages from the Socket
} catch (Exception e) {
// stop sender first
stopSender();
socket.close();
String line;
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
line = bufferedReader.readLine();
//Asks if the user want to connect to other server
// start a new sender
startSender();
}
}
Alternatively, there is a more elegant but complex solution: use non-blocking I/O. However, Java doesn't support selectable System.in
directly, so you would need to write JNI/JNA code.
Anyway, there is no easy solution to this.
Upvotes: 1
Reputation: 1
From your description, I understand that you want to loop through some plain text from System.in and when encountering errors, call method2 to close the Socket. I think you can establish a check to first see if the specific line would throw an error or not.
Again, I assume that the error happens when sending to the Socket. Therefore, I think you can create a dummy instance that would get the problematic line instead of sending it directly to the current one. This way, you assure that you can predict an error line and keep it away from the main instance.
Another suggestion would be to have your own way of identifying errors, instead of having to send lines directly to the client and see if they worked or not, you can have a method that would return whether the line is problematic or not based on some test cases.
I am sorry if this won't work for you, but I tried my best as I am a beginner :) More details would help as well, because with the ones provided by you I can't be sure of coding a solution, as I don't know the full problem.
Upvotes: 0