I'm writing GUI using JAVA for a console program. It starts and works well, but when i send "\n" or "\r\n" to it's stdin it doesn't react as it reacts if i simply start this program in Terminal and press "Enter".
This code is used to start process:
String cmd="example.exe";
process = new ProcessBuilder(cmd).start();
And this code is used to send "\n"
OutputStream outputStream = process.getOutputStream();
outputStream.write("\n".getBytes());
outputStream.flush();
In other thread i'm trying to read from this process
while ((line = is.readLine()) != null && !Thread.currentThread().isInterrupted()) {
...
}
How can i properly send "\n" to receive information from the process?
Update:
I need to send a new line symbol. Or "Press Enter".
I read out and error, both are empty.
Application always reports it's status as reaction to pressing enter. So no reaction is a bug.
Presumably you are expecting the newline written to outputStream to trigger something that you can read using is.
Here are a couple of possible causes:
You could be reading from the wrong stream. The external program might be writing to "standard error" and you are reading "standard output" or vice-versa.
The external application might be failing to flush. For example, it (or the I/O library it uses) might only flush output after each newline if the output is directed to an interactive output stream (e.g. a "console"). The pipe connecting program output to your JVM might not show up as interactive.
These are only guesses ...
If I was trying to debug this, I would try to determine whether the problem is that the newline doesn't get to example.exe, that the response doesn't get written / flushed by example.exe, or that the Java side is failing to read it ... for some reason.
Related
I have a made a socket connection between client and server. Everything is working good if i introduce the first comand on client, receiving the message i want from the server.
#server
public PrintWriter out;
out.println(res);
#client
public BufferedReader in = null;
String line;
line = in.readLine();
At the second time i run it won't show the message i send from server cause it will read \n so it will be an empty string. If i change this:
#server
out.println("\n"+res);
The first time i run now it will jump a line, printing just the \n. And the second time i run it will show the right message.
If i change now to:
out.println("\n\n"+res);
It will just show when i introduce something to send to the server and receive back after the 3rd time (the first 2 times it prints \n).
Don't know what to do to show always the message i send from the server. Any advice?
is there a way of knowing when or whether the flush() method of a BufferedOutputStream thread has finished successfully? In my case I'm using it for sending a simple string through a java.net.Socket. In the following code, the flush() method is run in parallel with the BufferedReader.read() method and the socket output is immediately blocked by the input read resulting in something that resembles a deadlock. What I would like to do is wait for the output to end, and then start reading the input.
Socket sk = new Socket("192.168.0.112", 3000);
BufferedOutputStream bo = new BufferedOutputStream(sk.getOutputStream());
bo.write(message.getBytes());
bo.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(sk.getInputStream()));
String line = br.readLine();
if (line.equals("ack")) {
System.out.println("ack");
}
sk.close();
Update
ServerSocket:
ServerSocket ss = new ServerSocket(3000);
System.out.println("server socket open");
while (true) {
Socket sk = ss.accept();
System.out.println("new connection");
BufferedReader br = new BufferedReader(new InputStreamReader(sk.getInputStream()));
String line = br.readLine();
System.out.println("received line: " + line);
BufferedOutputStream bo = new BufferedOutputStream(sk.getOutputStream());
bo.write("ack".getBytes()); bo.flush();
sk.close();
}
Update:
#Global Variable - the reason that read was blocking the socket is that it was waiting for the \n, indeed. Using
bo.write("ack\n".getBytes());
instead of
bo.write("ack".getBytes());
made it work.
Regarding the initial question, is there a way of knowing if flush() method has finished successfully, #Stephen C provided the answer:
there is no way to know that based on the Socket or OutputStream APIs.
The normal way to get that sort of assurance is to have the remote
application send an "reply" in response, and read it in the local
side.
This "reply" is implemented in the code sample and it works.
Is there a way of knowing when or whether the flush() method of a BufferedOutputStream thread has finished successfully?
It depends on what you mean by "finished successfully".
The flush() method ensures that all unsent data in the pipeline has been pushed as far as the operating system network stack. When that is done, then you could say that flush() has finished successfully. The way that you know that that has happened is that the flush() call returns.
On the other hand, if you want some assurance that the data has (all) been delivered to the remote machine, or that the remote application has read it (all) ... there is no way to know that based on the Socket or OutputStream APIs. The normal way to get that sort of assurance is to have the remote application send an "reply" in response, and read it in the local side.
In the following code, the flush() method is run in parallel with the BufferedReader.read() method and the socket output is immediately blocked by the input read resulting in something that resembles a deadlock.
The code that you are talking about is basically the correct approach. The way to wait for the response is to read it like that.
If it is not working, then you need to compare what the client and server side are doing:
Is the server waiting for the client to send something more? Maybe an end of line sequence?
Did the server sends the response?
Did it flush() the response?
A mismatch between what the client and server are doing can lead to a form or deadlock, but the solution is to fix the mismatch. Waiting for some kind of hypothetical confirmation of the flush() is not the answer.
UPDATE
The problem is indeed a mismatch. For example, the server writes "ack" but the client expects "ack\n". The same happens in the client -> server case ... unless message always ends with a newline.
Your code is reading reader.readLine() . Are your writing \n when writing? You may want to append \n to the string your are writing.
I tried to reproduce your problem. First, I ran in to some kind of blocking state too, until I realized, I was using readLine at Server-side, too. But the message I was sending did not have a concluding \n. Therefore, the serversocket was still waiting at its InputStream without sending the client the ACK through its OutputStream. I think, #Global Variable is right.
I am building a client/server application and I am trying to send a String to the client from a server thread using a PrintWriter. I construct my PrintWriter like this:
// Instantiate a PrintWriterwith a correctly implemented
// client socket parameter, and autoflush set to true
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
Assume, further, that the client is reading from the input stream with a BufferedReader, that is instantiated as such:
BufferedReader in = new BufferedReader(new InputStreamReader(client.server.getInputStream()));
and the client gets messages from the server with:
String serverMessage = in.readLine();
As you can see, I've set autoflushing to true. Let's say, now, that I want to send a simple message to a client. If I execute the statement:
out.println("Message to client");
Then the message is successfully sent. However, if I execute the statement:
out.print("Message to client");
then the message is not sent. Also:
out.print("Message to client");
out.flush();
does not work either.
This is a problem because I need to send a message to a client in a terminal and have them be able to respond on the same line. How do I send a message, using a PrintWriter, so that it gets flushed/sent to the client, but it does not send a newline character?
In your case it seems like you are using BufferedReader#readLine() which will read characters until a newline character or the end of stream is reached, blocking in the meantime. As such, you'll need your server to write that new line character.
An alternative is to read bytes directly instead of relying on BufferedReader#readLine().
why doesn't using a carriage return work?
The newline character is system-dependent. On Windows it is \r\n. On linux it is \n. You can get that with
System.getProperty("line.separator")
but you will need to get the server's.
I have noticed that in a few pieces of example code for a TCP chat program, written in Java, both the read string from client and send string to server both occur in main.
For example, here is a tutorial where I don't see the distinction between an input thread and in output thread... http://www.cise.ufl.edu/~amyles/tutorials/tcpchat/TCPChat.java
"BufferedReader input" and "PrintWriter output" are both used with a TCP Socket from within the same thread. As a complete novice, this confuses me because previously, if I had something that waits for input, like the "getch()" get character function from C, that thing that will hold up the thread (unless it is an event or an exception). Normally, when I imagine code in a thread being executed, I imagine it being executed line by line, with occasional jumps in execution for exceptions and events. But writing to a stream and reading from a stream is neither an exception nor an event - I don't know what the main thread would do if it received an input string and was supposed to send out an output string both at the same moment. Is the stream itself actually handled by some other thread or some other program, like the terminal or the OS?
I had felt so weird about this that I split the chat program into two separate threads to make me feel more comfortable - one thread for receiving strings from the TCP socket and another thread for sending strings out through the same socket. Can someone provide an explanation as to why my act of splitting input and output into two separate threads is totally unnecessary? And before someone marks this down due to lack of research and understanding, I did my best to read online Java tutorials on Sockets and I have had experience writing to and reading from streams (terminal and plain text file).
case CONNECTED:
try {
// Send data
if (toSend.length() != 0) {
out.print(toSend); out.flush();
toSend.setLength(0);
changeStatusTS(NULL, true);
}
// Receive data
if (in.ready()) {
s = in.readLine();
if ((s != null) && (s.length() != 0)) {
// Check if it is the end of a trasmission
if (s.equals(END_CHAT_SESSION)) {
changeStatusTS(DISCONNECTING, true);
}
// Otherwise, receive what text
else {
appendToChatBox("INCOMING: " + s + "\n");
changeStatusTS(NULL, true);
}
}
}
}
catch (IOException e) {
cleanUp();
changeStatusTS(DISCONNECTED, false);
}
break;
I took this code snippet from the "main procedure" of the link you provided.
The method that would halt the thread from continuing like you were talking about is in.readLine(); The thread would wait until there was something to read from the input stream before continuing. I would like to point out the if statement " if(in.ready()) " By having that if statement there, the code checks first if the input stream has something to read. Otherwise, it skips over it and continues.
I have a utility where Jmeter sends a request and the utility sends back response to Jmeter. When load increases, the Utility shuts down with an "EXCEPTION_ACCESS_VIOLATION".
Since it is an error, I am not able to handle it in a catch block. I made a second utility to restart the first utility when the error occurs. Below is the code of the second, restart, utility. In this second utility's code, at the second while, my program sometimes hangs. How do I detect this and restart the process?
public static void main(String[] args)
{
String line = null;
String currPID = null;
try
{
while(true)
{
Process process = Runtime.getRuntime().exec("java -XX:+HeapDumpOnOutOfMemoryError -Xms250M -Xmx500M -XX:ErrorFile=NUL ws ");
BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
while ((line = input.readLine()) != null) //Program stucks at this Line
{
if(line.trim().length() != 0)
{
if(line.startsWith("PID"))
{
currPID = line.substring(line.indexOf("#")+1);
}
}
}
System.out.println("Ended");
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
I analysed process through jvisualvm where i found two java process is in running mode when i start second(restart) utility. I can see first utility is restarting regularly because its PID is changing frequently in jvisualvm and same happening in task manager. Everything is going on very well manner.
After sometime i found only one process is in Jvisualvm ie second(restart) utility.
It means first utility JVM is crashed just guessing not sure. Something unusual is happening here. Because if JVM is crashed so It should be restarted.
So i opened task manager and found first utility PID exists there but it is not changing as happening in starting. If i kill the process(first utility) explicitly from task manager.
Seconds utility again restarts first utility same thing happens again, After some time first utility disappeared from jvisualvm, exists in taskmanager and delete process from taskmanager. What needs to do?
Try using .ready() function.
try {
if (stdError.ready())
{
while((line= stdError.readLine()) != null){
logger.error(line);
}
}
}
Do the same for the stdout.
It worked like a charm for me.
Your problem with hanging appears to be at the call to readLine.
readLine is for reading lines. The method will not return until the call is sure the end of line has been reached. It expects either a newline character or the complete cease of communications.
Is your first utility not sending a new line char?
Does your first utility fail to close the stream?
Your while call will hang indefinitely if the answer to both questions is yes.
You might be better off consuming with a custom implementation of the Scanner class.
Try to use getErrorStream() it'll catches the error message, if you use getInputStream() it'll reads only the success message or feedback messages.
for ex: if you execute the following command & read the process message using getInputStream(),
Process process = Runtime.getRuntime().exec("net use u: \\sharedIP\sharedFolder");
BufferedReader input = new BufferedReader(new inputStreamReader(process.getInputStream()));
you can only get feedback messages like "network drive connected successfully" but not the error messages.
if you use getErrorStream() to read the process message it'll read the error messages like "the network drive was not found". when the process executed it'll give a message to either getInputStream() or getErrorStream(). so use both method to read the message from the process, if i'm correct this'll work. I'm just trying to give you an idea but i'm not sure.