I know that InputStreams are for reading, and OutputStreams are for writing... but if I have an application that passes all data from an InputStream to the remote side and pushes all received data from that remote side to the OutputStream and I need to send dynamic data to that remote side... how would I enter it into the InputStream? I can do this easily in the Java console since anything entered in is put into System.in and sent to that remote side, and anything coming back is processed through System.out, but obviously I cannot use a Java console in production. How would I emulate this functionality e.g. create a button that sends "command X\r" as if it were typed into the java console?
Note: For background, I'm using JSch to SSH into a Cisco ASA. Where I have set Channel.setInputStream(System.in) and Channel.setOutputStream(System.out) to communicate through console successfully.
I am not familiar with JSch, and I suspect you have this backwards. First, according to their example, you should actually be executing commands with Channel.setCommand(). Then you can use Channel.getInputStream() to obtain a stream that you can read the remote response from.
That aside, a cursory glance at the documentation seems to suggest that you should use the channel's existing streams and read to / write from them, e.g.:
OutputStream out = Channel.getOutputStream();
String str = "command X\r";
out.write(str.getBytes("us-ascii"));
This would make more sense and is much easier to deal with on your end.
However, as to the general question regarding InputStreams: You can use any InputStream as a source for data. It just so happens that System.in is one that comes from standard input (which is essentially a file).
If you want to use data constructed on the fly, you could use a ByteArrayInputStream, e.g.:
String str = "command X\r";
InputStream in = new ByteArrayInputStream(str.getBytes("us-ascii"));
// do stuff with in
You can use any character encoding you want if us-ascii is not appropriate.
But, again, I suspect you are doing this slightly backwards.
Related
I have a problem in my server/client TCP multiplayer game whenever I try to send too many messages in a short time (usually over 20 messages in the arc of 20 millis). After a while the messages start to arrive corrupted for some reason (like with integers in place of strings that usually get me a NumberFormatException).
I send informations as Strings using a DataOutputStream and read them with a Scanner.
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
in = new Scanner(inputStream);
out = new DataOutputStream (outputStream);
My questions are: should I use something different from the DataOutputStream/Scanner combination? Is there a faster combination? Should I turn the strings into bytes before sending them?
The strings I send are usually composed by both integers and strings, like "m 2 215 123" or "ep 2".
Expanding on #EJP's answer, the corruption you are experiencing is a result of an application programming error of some kind.
If you are using DataOutputStream to write the data, you should use DataInputStream to read it. And make sure that the sequence of write calls exactly matches the sequence of read calls.
If you want to read using a Scanner, then you need to format the data as text, and use a Writer to write it. (Make sure that you use the same character encoding scheme at both ends, and avoid doing nasty things like mapping binary data to text via String(byte[]) ... 'cos they tend to break.)
If you are either reading or writing the data using multiple threads that read from / write to a single stream, then you need to use some kind of locking to ensure that the messages interleave correctly / cleanly. Streams are typically NOT thread-safe.
As to whether JSON will give you better performance, you probably need to do some experiments to be sure. Among other things, it will depend on the complexity of the data and the way you chose to encode it in the non-JSON case. (But I'd expect DataOutputStream / DataInputStream to be fastest if you chose an appropriate encoding.)
the message start to arrive corrupted
No they don't. The messages don't arrive corrupted. You're just getting out of sync, because you're using a poorly defined application protocol. Use DataInputStream and DataOutputStream symmetrically, as suggested by #JimGarrison.
I have written the server socket code in java. The relevant lines are:
byte[] bRecieved = new byte[440] ;
1int i =in.read(bRecieved);
Arrays.toString(bRecieved);
This works fine if the client is written in java
byte[] bSend = {1,2,3,4};
DataOutputStream out =
new DataOutputStream(outToServer);
out.write(bSend);
But the Client is written in C++. The code for sending is:
if (client.connect(serverIP, serverPort)) {
String msg="Hello Server";//Message to be sent
client.println(msg);//send the message
}
My question is , how do I communicate with the java server wanting bytes? The connection is successful and bytes are printed on the server console. But they are not "Hello Server". Do I have to iterate through the bytes and interpret them as chars? Chars and int are 1 byte in c++.
Please clarify this situation if possible.
Thanks in advance!
What library are you using for your C++ sockets?
You might try flushing the stream?
The C++ client is line-buffered by default. This means it won't actually send the data until either a newline is pushed onto the outbound data or the buffer holding data to be sent fills beyond a certain point (system dependent). If you want to see this in action set your msg string to "Hello Server\n". Your data should be sent right away.
The flush() command says, "send all data now, regardless of how much is in the buffer." So you can choose to do one other the other, either call flush() or append a newline. Of course if you use the newline, the Java process will receive a newline character in addition to the string, which may or may not be what you want. Generally, when performing network operations, you want to call flush() whenever you're done adding things to the outbound buffer.
I've got a third party program which puts data into a windows named pipe.
I access the pipe with
String pipename = "\\\\.\\pipe\\the_pipe";
RandomAccessFile pipe = new RandomAccessFile(pipename, "r");
DataInputStream input = new DataInputStream(Channels.newInputStream(pipe.getChannel()));
So sometimes someone gets the 'perfect' idea to close the third party program before my small data converting tool which of course closes the pipe. When that happens, my tool writes down the last message received million times into the resultfile and successfully fills every hdd up to the last byte within hours, because I am not able to check if the pipe has been closed.
Things I've tried:
// checking file descriptor and file channel
if(!(pipe.getFD().valid() && pipe.getChannel().isOpen())) {
// quit
}
But both options do not trigger.
Is there a other way to access named pipes where such an information can be obtained?
Or do I have overlooked something?
When that happens, my tool writes down the last message received million times into the resultfile
Only if your tool ignores EOFExceptions and -1 return values from read().
I would recommend looking at JNA to access the named pipe directly. Yes, you can detect the pipe closure if you use JNA.
I have done so in a project called NuProcess available on github.com. Particularly, look at the com.zaxxer.nuprocess.windows package. Look at the WindowsProcess.createPipes() method for setting up pipes (the code creates both ends, you only need one).
On the read side, NuProcess is using Windows IOCompletionPorts for asynchronous I/O (in ProcessCompletions.java), which may be overkill for what you need (or not). But once you get your feet wet setting up the pipes, you should be able to figure it out from there reading the Microsoft API docs.
I am sending a plain text file to the user through a servlet.
I am using flatworm framework to build the flat file. I receive the file in the browser but is empty. So i want start the debugging analysing the outputstream before being sent.
How i can read the response before i send it in the servlet? I think is the same thing that asking how can i transform an OutputStream to an InputStream.
I already saw solutions that always involve ByteArrayOutputStream , and as you know when i call in the servlet response.getOutputStream() it returns me an OutputStream and not a ByteArrayOutputStream.
There seems to be some confusion somewhere, though I'm not sure exactly where.
What can you do with an OutputStream? Why, you can write to it, and that's about it. That means that if you're given (or look up) an output stream, it's up to you to supply the data - which means you already have it.
Perhaps on the other hand, you're not directly calling write on the OutputStream yourself, but passing this stream into the flatworm library (which will in turn write output to it). In that case, there's your debugging "hook" right there - flatworm will write out the file to any output stream you send it. So in this case, instead of passing in the servlet's stream, you pass in a stream that you've created yourself.
That might be a ByteArrayOutputStream, which (after the flatworm method has returned) you can inspect to get the bytes written. At this point you could manually write them through to the response's output stream. Or maybe you need to do something slightly trickier and create your own stream wrapper which writes straight through to the underlying response stream but logs on the way - and pass this into flatworm.
The bottom line however is that if you're interacting with an output stream, then "your" code already has the data somewhere locally and it's just a matter of capturing/accessing that.
Alright, I'll get into the meat of things straight away:
I want to run a perl script from a java app (via ProcessBuilder), which will then parse an html page and find out some required information. I then want to pass that information back to my java app, and display that information in a JTextArea.
My knowledge of perl is VERY limited. My original thought was to write this data to a txt file, and then read that file with my java program, which could then display it to JTextArea pretty easily. However, this seems like an ugly solution, compared to simply returning a string.
Please let me know if there is a better way to do this. perhaps a completely different method than what I'm thinking of. Thanks,
Aelfhere
I think you want something like this
You can pass strings between processes only by using some type of inter-process communication: either a pipe or shared memory or using network.
Why can you not do in Java what you want to do in Perl?
when you use a ProcessBuilder you instantiate a Process Object it's java representation of a batch execution
Tipically you can hook process streaming via Java API.
Extracted from Process JAVA API:
abstract
InputStream getErrorStream()
Gets the error stream of the subprocess
abstract
InputStream getInputStream()
Gets the input stream of the subprocess
abstract
OutputStream getOutputStream()
Gets the output stream of the subprocess
If perl script write on standard output stream then you can read that output.
Generally, If process doesn't write on standard output stream then you cannot read it.